【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は謹んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.18671

このfor文を繰り返したいのですが・・・
投稿者---ライガー(2004/12/13 15:55:35)


下記の部分を繰り返して、各列の「1」の総和がすべて10になるようにしたいのですが、k<50などにすると実行結果が無限ループになってると思われます。このfor文を繰り返すにはどうすればよろしいのでしょうか?
/*0と1を規則に従って交換*/
for(k=0; k&lt;1; k++){
for(i=0; i&lt;56; i++){
margin[i] = 10; //一つの列に1が10個なければならないので
}
for(j=0; j&lt;56; j++){
for(i=0; i&lt;20; i++){
if(src[i][j] == 1){
margin[j] -= 1;
}
}
}
for(x1=0; x1&lt;56; x1++){
if(margin[x1] &lt; 0){ /* 1が多い */
for(x2=0; x2&lt;56; x2++){
if(margin[x2] &gt; 0){ /* 1が少ない */
change(x1, x2, src);
goto xxx;
}
}
}
}
xxx:
;
}
}

下記がプログラムです。
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <memory.h>

#define NINZUU 20  /* 人数 */
#define N 56       /* 日にちの長さ */
#define NUMBER 400  /* 必要人数*/
#define ARY_SIZE(x)  (sizeof(x)/sizeof(x[0]))

#ifndef true
#define true 1
#endif

#ifndef false
#define false 0
#endif


void shoki(int a[20][56]);
void set(int a[20], int b[20]);
int getTotal(int a[56]);
void change(int a, int b, int c[20][56]); 
int hyoka(int a[20][56]);

main()
{
    int i,j,k;
    int x1, x2;
    int margin[56];
    int src[20][56] = {  省略  }

    shoki(src);

    /*0と1を規則に従って交換*/
    for(k=0; k<1; k++){
        for(i=0; i<56; i++){
            margin[i] = 10;  //一つの列に1が10個なければならないので
        }
        for(j=0; j<56; j++){
            for(i=0; i<20; i++){
                if(src[i][j] == 1){
                    margin[j] -= 1;
                }
            }
        }
        for(x1=0; x1<56; x1++){
            if(margin[x1] < 0){ /* 1が多い */
                for(x2=0; x2<56; x2++){
                    if(margin[x2] > 0){ /* 1が少ない */
                        change(x1, x2, src);
                        goto xxx;
                    }
                }
            }
        }
        xxx:
        ;
    }
}

/* 初期値を決める */
void shoki(int a[20][56]){
    int i,j;
    int cnt = 0;
    int rest = 20;

    ///////////下記のように休み希望のところは9などを入れ変化させない//////////////
                a[0][7] = 9;
    ///////////////////////////////////////////////////////////////////////////////
  /* 人を適当に配置 */
    srand((unsigned)time(NULL));
    while(cnt < 400){
        i = rand() % NINZUU;
        j = rand() % N;
        if((a[i][j] == 0) && (getTotal(a[i]) < 18 || rest == 0) && (getTotal(a[i]) < 23)){
            a[i][j] = 1;
            cnt++;
            if(getTotal(a[i]) == 18){
                rest--;
            }
        }
    }
}

/* 行の1の合計値を返す */
int getTotal(int a[56]){
    int total = 0;
    int i;
    for(i=0; i<56; i++){
        if(a[i] == 1){
            total++;
        }
    }
    return total;
}

/* 交換 */
void change(int x1, int x2, int src[20][56]){
    int i,j;
    int box[20][56];
    int goodBox[20][56];  //このgoodBoxに、より良い並びになっているものを入れる
    int goodHyoka = 99999;
    for(i=0; i<20; i++){
        for(j=0; j<56; j++){
            box[i][j] = src[i][j];
        }
    }
    for(i=0; i<20; i++){
        if(box[i][x1] == 1){
            for(j=0; j<20; j++){
                if(box[j][x2] == 0){
                    box[i][x1] = 0;
                    box[j][x2] = 1;
                    if(goodHyoka > hyoka(box)){
                        goodHyoka = hyoka(box);
                        for(i=0; i<20; i++){
                            for(j=0; j<56; j++){
                                goodBox[i][j] = box[i][j];
                            }
                        }
                    }
                }
            }
        }
    }
    for(i=0; i<20; i++){
        for(j=0; j<56; j++){
            printf("%d",src[i][j]);
        }
        printf("\n");
    }
    printf("%d", hyoka(src));
    for(i=0; i<20; i++){
        for(j=0; j<56; j++){
            src[i][j] = goodBox[i][j];
        }
    }
    printf("\n\n");
    for(i=0; i<20; i++){
        for(j=0; j<56; j++){
            printf("%d",src[i][j]);
        }
        printf("\n");
    }
    printf("%d", hyoka(src));
}

/* 評価をする(低い方がいい) */
int hyoka(int src[20][56]){
    int i,j;
    int hyoka = 0;
    int count = 0;
    for(i=0; i<20; i++){
        for(j=0; j<56; j++){
            if(src[i][j]==1){
                count++;
            }
            else{
                if(count == 2)   hyoka += 1;
                if(count == 3)   hyoka += 3;
                if(count >= 4)   hyoka += 6;
                count = 0;
            }
        }
    }
    return hyoka;
}




この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:このfor文を繰り返したいのですが・・・ 18672 ライガー 2004/12/13 16:00:00
<子記事> Re:このfor文を繰り返したいのですが・・・ 18674 REE 2004/12/13 16:41:33


No.18672

Re:このfor文を繰り返したいのですが・・・
投稿者---ライガー(2004/12/13 16:00:00)


先のプログラムの省略の部分は以下の通りです。

int src[20][56] = {
      {2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,0,0,0,0,0,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,},
      {0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,0,0,0,0,0,3,3,2,2,2,2,2,3,3,},
    };



この投稿にコメントする

削除パスワード

No.18674

Re:このfor文を繰り返したいのですが・・・
投稿者---REE(2004/12/13 16:41:33)


>下記の部分を繰り返して、各列の「1」の総和がすべて10になるようにしたいのですが、k<50などにすると実行結果が無限ループになってると思われます。このfor文を繰り返すにはどうすればよろしいのでしょうか?

「思われる」ということは確認していないのですね?

とはいえ、このソースには無限ループが発生するような部分は見当たりませんし、実際に50にして実行してもちゃんとプログラムが終了しました。
あなたが何を問題としているのかさっぱり分かりません。



この投稿にコメントする

削除パスワード

No.18675

Re:このfor文を繰り返したいのですが・・・
投稿者---ライガー(2004/12/13 17:03:41)


私のパソコンでは実行結果の最後の方が「-858993460」という数字が
たくさん出てきてしまいます。何故ですか?
開発環境は
MEのVisual C++です。




この投稿にコメントする

削除パスワード

No.18677

Re:このfor文を繰り返したいのですが・・・
投稿者---REE(2004/12/13 17:13:54)


>私のパソコンでは実行結果の最後の方が「-858993460」という数字が
>たくさん出てきてしまいます。何故ですか?

同じように出てきましたよ。
初期化していない変数の値を使用しているからです。



この投稿にコメントする

削除パスワード

No.18679

Re:このfor文を繰り返したいのですが・・・
投稿者---ライガー(2004/12/13 18:14:49)


ありがとうございます。
int box[20][56] = {0};
    int goodBox[20][56] = {0};

上記のように変更したら、ちゃんと動くようになりました。
(goodBoxが最後まで{0}のままでしたが・・・)
ただ、先ほどのfor文のkの値を増やしても各列の「1」の総和が10には
なりませんでした。以下のfor文がちゃんと動いていれば、
「1」が多いある列を見つけ、「1」が少ないある列を探して交換
するので、いずれ各列の「1」の総和が10になるはずですよね?

for(k=0; k<100; k++){
        for(i=0; i<56; i++){
            margin[i] = 10;  //一つの列に1が10個なければならないので
        }
        for(j=0; j<56; j++){
            for(i=0; i<20; i++){
                if(src[i][j] == 1){
                    margin[j] -= 1;
                }
            }
        }
        for(x1=0; x1<56; x1++){
            if(margin[x1] < 0){ /* 1が多い */
                for(x2=0; x2<56; x2++){
                    if(margin[x2] > 0){ /* 1が少ない */
                        change(x1, x2, src);
                        goto xxx;
                    }
                }
            }
        }
        xxx:
        ;
    }



この投稿にコメントする

削除パスワード

No.18680

Re:このfor文を繰り返したいのですが・・・
投稿者---REE(2004/12/13 18:24:02)


>ただ、先ほどのfor文のkの値を増やしても各列の「1」の総和が10には
>なりませんでした。以下のfor文がちゃんと動いていれば、
>「1」が多いある列を見つけ、「1」が少ないある列を探して交換
>するので、いずれ各列の「1」の総和が10になるはずですよね?

3で埋まっている列をお忘れなく


この投稿にコメントする

削除パスワード

No.18685

Re:このfor文を繰り返したいのですが・・・
投稿者---ライガー(2004/12/13 19:33:53)


for文の中を以下のように変えてみました。3の列は1がないので
marginが10のままで、1がある列は必ず10未満になるため、
これで各列ごとの「1」の総和が10になるように動くと思ったんですが
これでもダメでした。ご指摘して下さった箇所はここで良かったですか?

if(0<margin[x2]<10){    /* 1が少ない */



この投稿にコメントする

削除パスワード

No.18686

Re:このfor文を繰り返したいのですが・・・
投稿者---shu(2004/12/13 19:51:46)


http://www9.plala.or.jp/sgwr-t/c/sec06-1.html
http://www9.plala.or.jp/sgwr-t/c/sec06-2.html
http://www9.plala.or.jp/sgwr-t/c/sec18.html


この投稿にコメントする

削除パスワード

No.18690

Re:このfor文を繰り返したいのですが・・・
投稿者---ライガー(2004/12/13 21:04:47)


読んでみてif文、for文についてはわかったつもりなのですが、
その上でも先ほどのfor文が思い通りに動かない理由がわかりません。
このfor文以外の箇所に間違いがあるのでしょうか?


この投稿にコメントする

削除パスワード

No.18694

Re:このfor文を繰り返したいのですが・・・
投稿者---shu(2004/12/13 22:08:41)


>読んでみてif文、for文についてはわかったつもりなのですが、

できれば演習もやってみて……。
2時間そこらで、全部わかるはずもないでしょうが、
ほんの少しでも、理解が深まれば良いと思います。

>その上でも先ほどのfor文が思い通りに動かない理由がわかりません。

『思い通り』の状態ということが、ご自身でわかってないんでしょう。
書き込みにおいても、『思い通り』の状態が、見えてきません。
(前回、前々回のスレッドを見てない方は、尚更)


この投稿にコメントする

削除パスワード

No.18695

Re:このfor文を繰り返したいのですが・・・
投稿者---RAPT(2004/12/13 22:55:47)


# ある有名な格言を思い出してしまった。
# プログラムは「思い通り」には動かない。「書いた通り」に動く。



この投稿にコメントする

削除パスワード

No.18696

Re:このfor文を繰り返したいのですが・・・
投稿者---ライガー(2004/12/13 23:07:55)


おっしゃる通りです。よく見直してみたところ
先ほどのif文のところを以下のようにしたら直りました。
if(0<margin[x2] && margin[x2]<10){    /* 1が少ない */


if文のところは(i=0;0<i<10;i++)とは、そういえば出来ないのですね。

ありがとうございました。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧