またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ファイブマン

またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#1

投稿記事 by ファイブマン » 14年前

またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.
以前もグリーディー法の問題でトピックを立てさせていただいたのですが,今度は別の入力ファイルから読み込んで解くという形式なのですが,ファイル入出力関数を使って読み込むのはわかるのですがそこで生じる先ほどの問題から変える部分をどうしたらいいかわかりません.
以下にソースコードを書き込むので何を補えばいいのか教えてください.
宜しくお願いします.
前回お世話になった質問:http://dixq.net/forum/viewtopic.php?f=3 ... 952#p76390
また,入力テキストファイルも(この形式で合っているかわからないのですが)記載します.それぞれSとがe前回の質問と同じようになっています.

コード:

#include<stdio.h>
#include<stdlib.h>


double calc(int S[9], int S_cost){
  int e, count = 0;
  
  // 有効な探査対象の個数を探す(a[e]が1の物)
  for (e = 0; e < 9; e++){
    if (S[e] == 1){
      count++;
    }
  }
  if (count == 0){
    return -1;
  }
  return ((double)S_cost) / count;
}



int main(void){
  
  int S_cost[] = {90, 34, 23, 30, 20, 98, 100, 2};
  int i, j,k, min_n;  
  double min_cost, cost_buf;
  FILE *fp;
  char s[256];
  if((fp = ("example_a.txt", "r")) == NULL){
    printf("file open error!!\n");
    exit(EXIT_FAILURE);	
  }
  while (fgets(s, 256, fp) != NULL) {
    
    
    printf("%s", s);
  }
  fclose(fp);	
  for(k=0; k<8; k++){
    min_n = -1;    
    for(i = 0; i < 8; i++){
      cost_buf = calc(S[i], S_cost[i]);
      
      if (cost_buf != -1)
 	{
	  if(min_n == -1){  
	    min_cost = cost_buf;
	    min_n = i;
	    
	  }
	  else{ 
	    if(cost_buf < min_cost){
	      min_cost = cost_buf;
	      min_n = i;  
	    }

入力テキストファイル
	  }
	} 
    }
    
    
    
    printf("コスト%.1f, i = %d\n",min_cost, (min_n)+1);
   
    
    for(i =0; i < 9; i++){
      if((S[min_n][i]) == 1)
	for(j = 0; j < 8; j++){
	  if((S[j][i]) == 1)     
	    S[j][i] = -1;
	  
	} 
    } 
   
    
    
  }
  
  return 0;
}

コード:

S[5][14]={
{1,0,0,0,0,0,0,1,0,0,0,0,0,0}
{0,1,1,0,0,0,0,1,1,1,0,0,0,0}
{0,0,0,1,1,1,1,0,0,0,1,1,1,1}
{1,1,1,1,1,1,1,0,0,0,0,0,0,0}
{0,0,0,0,0,0,0,1,1,1,1,1,1,1}
}

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#2

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました: 以前もグリーディー法の問題でトピックを立てさせていただいたのですが,今度は別の入力ファイルから読み込んで解くという形式なのですが,ファイル入出力関数を使って読み込むのはわかるのですがそこで生じる先ほどの問題から変える部分をどうしたらいいかわかりません.
まず、ファイルから読み込みSを作るプログラムをグリーディー法のプログラムとは別のところで組んでみませんか?
そのプログラムが完成後、読み込んでSを作る処理をグリーディー法のプログラムに移して、ファイルからの読み込みに変更した結果必要となった修正を当てるという方向性でどうでしょう?
ファイブマン さんが書きました: また,入力テキストファイルも(この形式で合っているかわからないのですが)記載します.それぞれSとがe前回の質問と同じようになっています.

コード:

S[5][14]={
{1,0,0,0,0,0,0,1,0,0,0,0,0,0}
{0,1,1,0,0,0,0,1,1,1,0,0,0,0}
{0,0,0,1,1,1,1,0,0,0,1,1,1,1}
{1,1,1,1,1,1,1,0,0,0,0,0,0,0}
{0,0,0,0,0,0,0,1,1,1,1,1,1,1}
}
このデータセットは複雑じゃないですか?

コード:

5 14
1 0 0 0 0 0 0 1 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 1 1 1 1 0 0 0 1 1 1 1
1 1 1 1 1 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1
こちらだと同じ内容を表せていて、その上読み込みが非常に楽になるのですがいかがでしょう?
それからSのコストのデータセットも必要なんじゃないでしょうか?

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#3

投稿記事 by ファイブマン » 14年前

bitter_foxさん,前回の質問ではありがとうございました.またお世話になります.

わかりました!まずァイルから読み込みSを作るプログラムをつくってみたいと思います.

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#4

投稿記事 by ファイブマン » 14年前

すみません,コストの件忘れていました.とりあえず今回はすべて1にしてやろうと思うのですがテキストファイルにどう盛り込めばいいのでしょうか.

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#5

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:すみません,コストの件忘れていました.とりあえず今回はすべて1にしてやろうと思うのですがテキストファイルにどう盛り込めばいいのでしょうか.
オーソドックスな形式をいくつか挙げておくので参考にしてください。

1.ファイルを二つに分ける
FileA

コード:

5 14
1 0 0 0 0 0 0 1 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 1 1 1 1 0 0 0 1 1 1 1
1 1 1 1 1 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1
FileB

コード:

90 34 23 30 20
2.ファイル一つにまとめて書いておく

コード:

5 14
90 34 23 30 20
1 0 0 0 0 0 0 1 0 0 0 0 0 0
0 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 1 1 1 1 0 0 0 1 1 1 1
1 1 1 1 1 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1
3.各データセットの先頭、もしくは末尾に書いておく

コード:

5 14
1 0 0 0 0 0 0 1 0 0 0 0 0 0 90
0 1 1 0 0 0 0 1 1 1 0 0 0 0 34
0 0 0 1 1 1 1 0 0 0 1 1 1 1 23
1 1 1 1 1 1 1 0 0 0 0 0 0 0 30
0 0 0 0 0 0 0 1 1 1 1 1 1 1 20
もしファイル構成等指定があるのであればそれに準じてください。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#6

投稿記事 by ファイブマン » 14年前

では2番の方法でやってみたいと思います.
これをグリーディー法に組み込む前段階として,ファイル読み込みをするプログラムをつくるにはまずどうとっかかればよいでしょうか?
とりあえずテキストファイルを読み込んで使用する関数に対応できるようにするのでしょうか.わからないのですみませんが宜しくお願いします.

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#7

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:では2番の方法でやってみたいと思います.
これをグリーディー法に組み込む前段階として,ファイル読み込みをするプログラムをつくるにはまずどうとっかかればよいでしょうか?
とりあえずテキストファイルを読み込んで使用する関数に対応できるようにするのでしょうか.わからないのですみませんが宜しくお願いします.
数値の読み込みにはfscanfを使用するのが手っ取り早いと思います。
http://www.kiso.tsukuba.ac.jp/~makimura ... de128.html

SやS_costはポインタにして動的に確保するようにします。
大きさにはデータセットの先頭二つを使用します。(例では5と14)

それから、前回の質問は解決しましたか?
http://dixq.net/forum/viewtopic.php?f=3&t=9389&start=30
解決した場合は結果を投稿欄下部の[解決!]をチェックしたうえで投稿してください。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#8

投稿記事 by ファイブマン » 14年前

すみません、勉強不足のため言っていることがよく理解できませんでした。
bitter_fox さんが書きました: SやS_costはポインタにして動的に確保するようにします。
大きさにはデータセットの先頭二つを使用します。
”動的に”、”大きさ”などがよくわかりません。
大きさというのは
#define FSCANF_BUFFER_LEN 128
のところなのでしょうか?

どちらもどう表現すればよいのでしょうか、回答よろしくお願いします。

コード:

#include <stdio.h>
#define FSCANF_BUFFER_LEN 128
int main(void)
{
    FILE *fp;
    double x, y;
    int n;
    int *S, *S_cost;
    
    fp = fopen("data.txt", "r");
    if(fp == NULL)
        exit(0);

    while( fscanf(fp, "%lf", &x, &y) != EOF ){
        printf("%g %g\n", x, y);
    }

    fclose(fp);
    return 0;
}

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#9

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:
bitter_fox さんが書きました: SやS_costはポインタにして動的に確保するようにします。
大きさにはデータセットの先頭二つを使用します。
”動的に”、”大きさ”などがよくわかりません。
大きさというのは
#define FSCANF_BUFFER_LEN 128
のところなのでしょうか?

どちらもどう表現すればよいのでしょうか、回答よろしくお願いします。
動的に確保するにはmalloc系の関数を使用します。
http://www9.plala.or.jp/sgwr-t/lib/malloc.html
http://www.pc.uec.ac.jp/sp/hshrkw/edu/p ... ming-6.htm - 動的確保と静的確保の違いについても触れられていますので参考にして下さい。

大きさというのはデータセットの先頭二つ、例で言うと5と14です。
この5は探査軌道の数に当たり、14が探査対象の個数に当たります。

元のプログラムではSは二次元の配列として書かれているのでここでもそれに準じて二次元で作っていきます。
ですのでSはint **Sとして宣言しておいてください。
2次元な確保については、
http://www.geocities.jp/ky_webid/c/055ans.html
の問題③を参考にしてください。
ファイブマン さんが書きました:

コード:

    double x, y;

    while( fscanf(fp, "%lf", &x, &y) != EOF ){

データセットの全ての項は整数ですのでxとyも整数にしておいてください。

ところでこの課題の期限はいつまでなのでしょうか?
LP緩和による近時問題の実装について
ファイブマン さんが書きました: 今これとはまた別の問題でここにお世話になっている者なのですが、そっちに気を取られ、べつの課題(期限が水曜夜)があったのを忘れていました。
そこで厚かましいのですが、そちらの方の解答を教えていただけないでしょうか。これまでのグリーディー法のことなどをうまく使ったりしてやる課題なのですが、それに時間がかかってしまい期限中にこのLP緩和までたどり着くことはできませんでした。
このべつの課題(期限が水曜夜)というのはLP緩和の方の事ですよね?
となると、この問題についても期限があるのではないでしょうか?

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#10

投稿記事 by ファイブマン » 14年前

回答ありがとうございます.
とりあえず以下でやってみたのですが無限ループが発生してしまいました.
読み込んだファイルを表示するのはこうではないとはわかっているのですがこの形で,表示する方法がわかりません.

そしてLP緩和の問題の件なのですが,別の課題というのがこれで,これまた期限が同じく水曜夜です.ですのでおそらくLP緩和の方は間に合わないと踏んだのでここに頼ろうと考えました.

コード:

#include <stdio.h>
#include <stdlib.h>


int main(void)
{
  
  FILE *fp;
  
  int **array = (int**)malloc(sizeof(int*)*5);  /* ポインタの配列を割り当てる */
  int i, j;
  int x, y;
  int n;
  int **S, *S_cost;
  
  fp = fopen("example_a.txt", "r");
  if(fp == NULL)
    exit(0);
  while( fscanf(fp, "%d", &x, &y) != EOF ){
    for(i=0; i<14; ++i)  /* 配列の各列について、5要素分の領域を割り当てる */
      {
	array[i] = (int*)malloc(sizeof(int)*14);
      }
    
    for(i=0; i<14; i++)  /* 列 */
      {
	for(j=0; j<5; j++)  /* 行 */
	  {
	 
	    //	 printf( "%d ", array[x][y] );
	    printf("%d %d\n", &i, &j);
	  }
	printf( "\n" );
      }
    for(i=0; i<5; i++)
      {
	free( array[i] );
      }
    free( array );
    
    
  }
  
  fclose(fp);
  return 0;
}

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#11

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:回答ありがとうございます.
とりあえず以下でやってみたのですが無限ループが発生してしまいました.
まず、SとS_costを利用する準備をします。
ファイルから先頭の二つのデータを読み込みます。(仮にS_size, E_size)
次に、SとS_costに対してS_size*sizeof(int*)の大きさでメモリを確保します。
Sのそれぞれに対してE_size*sizeof(int)の大きさでメモリを確保します。

次にS_costを読み込み、その次にSを読み込みます。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#12

投稿記事 by ファイブマン » 14年前

bitter_fox さんが書きました: まず、SとS_costを利用する準備をします。
ファイルから先頭の二つのデータを読み込みます。(仮にS_size, E_size)
次に、SとS_costに対してS_size*sizeof(int*)の大きさでメモリを確保します。
Sのそれぞれに対してE_size*sizeof(int)の大きさでメモリを確保します。
は自分なりにやってはみたのですがこれで合っているのでしょうか.
そしてその後の
bitter_fox さんが書きました: 次にS_costを読み込み、その次にSを読み込みます。
がやりかたがわからなく詰まってしまいました.ファイルのその読みたい部分だけを読むというのはどうすればいいのでしょうか.
御回答宜しくお願いします.

コード:

#include <stdio.h>
#include <stdlib.h>


int main(void)
{
  FILE *fp;
  int **array = (int**)malloc(sizeof(int*));  /* ポインタの配列を割り当てる */
  int i, j;
  int **S, *S_cost;
  int S_size, E_size;
  
  fp = fopen("example_a.txt", "r");
  if(fp == NULL)
    exit(0);
  
  while( fscanf(fp, "%d", &S_size, &E_size) != EOF ){
    
    **S = S_size*sizeof(int*);
    *S_cost = S_size*sizeof(int*);
    for(i = 0; i < S_size*sizeof(int*); i++){
      for(j = 0; j < E_size*sizeof(int*); j++){
      }
    }   
    // free();
  }
  
  fclose(fp);
  return 0;
}


アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#13

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:
bitter_fox さんが書きました: まず、SとS_costを利用する準備をします。
ファイルから先頭の二つのデータを読み込みます。(仮にS_size, E_size)
次に、SとS_costに対してS_size*sizeof(int*)の大きさでメモリを確保します。
Sのそれぞれに対してE_size*sizeof(int)の大きさでメモリを確保します。
は自分なりにやってはみたのですがこれで合っているのでしょうか.

コード:

  while( fscanf(fp, "%d", &S_size, &E_size) != EOF ){
何も先頭二つの読み込みでループにする必要はないですよね。
それにfscanf(fp, "%d", &S_size, &E_size)が二回目に回ってきたときは先頭ではないですし・・・

単純に先頭二つを込みこむなら、他の読み込みを行う前に

コード:

fscanf(fp, "%d%d", &S_size, &E_size); // 二項目読み込むので"%d%d"
とするだけでいいですよね。
ファイブマン さんが書きました: そしてその後の
bitter_fox さんが書きました: 次にS_costを読み込み、その次にSを読み込みます。
がやりかたがわからなく詰まってしまいました.ファイルのその読みたい部分だけを読むというのはどうすればいいのでしょうか.
読みたい個数回分だけループを用いてfscanf("%d", &n)が実行されるようにすればよいですよね。
まず、S_costの読みたい個数はいくつでしょう?これは具体的な値はファイル(example_a.txt)に書かれていて先に変数に読み込まれています。
その変数を用いてループを作ります。
代入先はS_costの要素ですのでそれに合わせて上の&nを変更します。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#14

投稿記事 by ファイブマン » 14年前

bitter_fox さんが書きました: まず、S_costの読みたい個数はいくつでしょう?これは具体的な値はファイル(example_a.txt)に書かれていて先に変数に読み込まれています。
その変数を用いてループを作ります。
代入先はS_costの要素ですのでそれに合わせて上の&nを変更します。
S_costは5つ読みたいので上部に
#define COST 5
としてみたのですがこれではファイルから直接読み込むわけではないのでダメなのですよね?
入力ファイルの特定の場所の数値を読み込むというのはどうすればできるのでしょうか.

コード:

#include <stdio.h>
#include <stdlib.h>
#define COST 5

int main(void)
{
  FILE *fp;
  int **array = (int**)malloc(sizeof(int*));  /* ポインタの配列を割り当てる */
  int i, j, n;
  int **S, *S_cost;
  int S_size, E_size;
  
  fp = fopen("example_a.txt", "r");
  if(fp == NULL)
    exit(0);
  
  fscanf(fp, "%d%d", &S_size, &E_size);
    
    **S = S_size*sizeof(int*);
    *S_cost = S_size*sizeof(int*);
    for(i = 0; i < COST; i++){
      fscanf("%d", &S_cost);
        }   
    // free();
  
  
  fclose(fp);
  return 0;
}

コード:

5 14
1 1 1 1 1
1,0,0,0,0,0,0,1,0,0,0,0,0,0
0,1,1,0,0,0,0,1,1,1,0,0,0,0
0,0,0,1,1,1,1,0,0,0,1,1,1,1
1,1,1,1,1,1,1,0,0,0,0,0,0,0
0,0,0,0,0,0,0,1,1,1,1,1,1,1



アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#15

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:
bitter_fox さんが書きました: まず、S_costの読みたい個数はいくつでしょう?これは具体的な値はファイル(example_a.txt)に書かれていて先に変数に読み込まれています。
その変数を用いてループを作ります。
代入先はS_costの要素ですのでそれに合わせて上の&nを変更します。
S_costは5つ読みたいので上部に
#define COST 5
としてみたのですがこれではファイルから直接読み込むわけではないのでダメなのですよね?
入力ファイルの特定の場所の数値を読み込むというのはどうすればできるのでしょうか.
特定の場所の数値を読み込むというのはランダムアクセスとして読み込むという事でしょうか?
そのようにする必要はありません、順次アクセスで結構です。
というのも先頭二つを読み込んだ後に待っているデータはS_costの一つ目のデータです。

コード:

5 14 // 先頭二つ(探査軌道の数と探査対象の数)
1 1 1 1 1 // S_costの値達
1 0 0 0 0 0 0 1 0 0 0 0 0 0 // S[0][0]・・・
0 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 1 1 1 1 0 0 0 1 1 1 1
1 1 1 1 1 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1
ところで、Sに関するデータセットは,区切りで行くのですか?

5という数字はファイルの一つ目のデータですね。でもってその値はプログラム内でS_sizeという値に読み込まれています。
ですので、S_size回読み出して、S_costに代入していきます。
ファイブマン さんが書きました:

コード:

#define COST 5

int main(void)
{  
  fscanf(fp, "%d%d", &S_size, &E_size);
    
    **S = S_size*sizeof(int*);
    *S_cost = S_size*sizeof(int*);
    for(i = 0; i < COST; i++){
      fscanf("%d", &S_cost);
        }   
}
まずSとS_costに対して適切にメモリを確保しましょう。
それから&S_costは適切でしょうか?int**型となってしまいます。この場合読み込まれた値はint*型として働き、int型としては働きません。intとして働かせるためにはint*型を指定する必要があります。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#16

投稿記事 by ファイブマン » 14年前

bitter_fox さんが書きました: ところで、Sに関するデータセットは,区切りで行くのですか?
やめて、空白で区切るようにします。
bitter_fox さんが書きました: それから&S_costは適切でしょうか?int**型となってしまいます。この場合読み込まれた値はint*型として働き、int型としては働きません。intとして働かせるためにはint*型を指定する必要があります
混乱してしまいました。&costはつまりこの場合、1 1 1 1 1らを読み込むことですよね?
int*型の何かここで初期化しなければということでしょうか。
以下、少し変えてみたのですがご指摘よろしくお願いします。

コード:

#include <stdio.h>
#include <stdlib.h>
#define COST 5
 
int main(void)
{
  FILE *fp;
  int **array = (int**)malloc(sizeof(int*));  /* ポインタの配列を割り当てる */
  int i, j, n;
  int **S, *S_cost;
  int S_size, E_size;
  
  fp = fopen("example_a.txt", "r");
  if(fp == NULL)
    exit(0);
  
  fscanf(fp, "%d%d", &S_size, &E_size);
fscanf(fp, "%d",S);
    **S = S_size*sizeof(int*);
    *S_cost = S_size*sizeof(int*); 
    *S = 
    for(i = 0; i < S_size; i++){
      fscanf("%d", &S_cost[i]);
      for(j= 0; j<E_size; j++){     
         fscanf(fp, "%d",&S[j]);   
       } 
   } 
// free();
  
  
  fclose(fp);
  return 0;
}

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#17

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました: 混乱してしまいました。&costはつまりこの場合、1 1 1 1 1らを読み込むことですよね?
int*型の何かここで初期化しなければということでしょうか。
残念ながら違います。
&S_costとした場合は1を読み込んでS_cost(int*型)に値を設定します。
S_cost[0]~S_cost[4]に値を設定していく場合は次のようにします。

コード:

for (i = 0; i < 5; i++)
{
	fscanf(fp, "%d", &S_cost[i]);
}
このコードを実行するためにはS_cost[0]~S_cost[4](int型5個分)の領域を確保しておかなければなりません。
確保するためには前途の通りmalloc、calloc等の関数を使います。

コード:

S_cost = (int*)malloc(5 * sizeof(int));
S_cost = (int*)calloc(5, sizeof(int));
// 主にこの二つのどちらか(違いはcallocの方は各要素を0で初期化します)
Sについても同様ですが、二次元になる点に注意してください。
bitter_fox さんが書きました: 2次元な確保については、
http://www.geocities.jp/ky_webid/c/055ans.html
の問題③を参考にしてください。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#18

投稿記事 by ファイブマン » 14年前

bitter_fox さんが書きました: &S_costとした場合は1を読み込んでS_cost(int*型)に値を設定します。
S_cost[0]~S_cost[4]に値を設定していく場合は次のようにします。

コード:

for (i = 0; i < 5; i++)
{
    fscanf(fp, "%d", &S_cost[i]);
}
ループの中のi<5はi<S_sizeではダメなのでしょうか。この入力ファイル以外にも対応するように読み込ませたいのでこうならよいのではと思ったのですがどうでしょうか。
bitter_fox さんが書きました: Sについても同様ですが、二次元になる点に注意してください。

コード:

 for(i = 0; i < 5; i++){
      fscanf("%d", &S_cost[i]);
        for(j= 0; j < 14; j++){     
            fscanf(fp, "%d",&S[i][j]);   
       } 
   } 
S_costについてのループ中でさらにSの方もできるのかと思い、こうしたのですがこれはどうでしょうか。
現在、事情があってコンパイルができない状況にあって自分で確認することができません。
回答よろしくお願いします。

コード:

#include <stdio.h>
#include <stdlib.h>
#define COST 5
 
int main(void)
{
  FILE *fp;
  int **array = (int**)malloc(sizeof(int*));  /* ポインタの配列を割り当てる */
  int i, j, n;
  int **S, *S_cost;
  int S_size, E_size;
  
  fp = fopen("example_a.txt", "r");
  if(fp == NULL)
    exit(0);
  
  fscanf(fp, "%d%d", &S_size, &E_size);
  fscanf(fp, "%d",S);
    **S = S_size*sizeof(int*);
    *S_cost = S_size*sizeof(int*); 
    S_cost = (int*)calloc(5, sizeof(int)); 
   S = (int**)calloc(5, sizeof(int*)); 
    for(i = 0; i < 5; i++){
      fscanf("%d", &S_cost[i]);
        for(j= 0; j < 14; j++){     
            fscanf(fp, "%d",&S[i][j]);   
       } 
   } 
 free(S_cost);
  
  
  fclose(fp);
  return 0;
}

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#19

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました: ループの中のi<5はi<S_sizeではダメなのでしょうか。この入力ファイル以外にも対応するように読み込ませたいのでこうならよいのではと思ったのですがどうでしょうか。
そうですね、例として5を上げさせていただきました、実際にはS_sizeやE_sizeを使ってください。
ファイブマン さんが書きました:
bitter_fox さんが書きました: Sについても同様ですが、二次元になる点に注意してください。

コード:

 for(i = 0; i < 5; i++){
      fscanf("%d", &S_cost[i]);
        for(j= 0; j < 14; j++){     
            fscanf(fp, "%d",&S[i][j]);   
       } 
   } 
S_costについてのループ中でさらにSの方もできるのかと思い、こうしたのですがこれはどうでしょうか。
これだと読み込む順番としては

コード:

S_cost[i] S[i][0] S[i][1] ... S[i][13]
の様になってしまいます。(最初の方に上げたファイル形式の「3.各データセットの先頭に書いておく」であれば正しいです)

まずはS_costについて読み込んで、
その読み込みが終わってからS[j]について読み込みましょう。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#20

投稿記事 by ファイブマン » 14年前

bitter_fox さんが書きました: まずはS_costについて読み込んで、
その読み込みが終わってからS[j]について読み込みましょう。

コード:

for(i = 0; i < S_size; i++){
      fscanf("%d", &S_cost[i]);
      } 
    for(i = 0; i < S_size; i++){
        for(j = 0; j < S_size; j++){
          fscanf("%d", &S[i][j]);  
          }
    }
こうすればS_costを読み込んだ後改めてSを読み込むのでしょうか?

それから、メモリを確保した後、free()で逃がす作業もやらなくてはいけないのですか。
ご回答よろしくお願いいたします。

コード:

#include <stdio.h>
#include <stdlib.h>
#define COST 5
 
int main(void)
{
  FILE *fp;
  int **array = (int**)malloc(sizeof(int*));  /* ポインタの配列を割り当てる */
  int i, j, n;
  int **S, *S_cost;
  int S_size, E_size;
  
  fp = fopen("example_a.txt", "r");
  if(fp == NULL)
    exit(0);
  
  fscanf(fp, "%d%d", &S_size, &E_size);
  fscanf(fp, "%d",S);
    **S = S_size*sizeof(int*);
    *S_cost = S_size*sizeof(int*); 
    S_cost = (int*)calloc(5, sizeof(int)); 
   S = (int**)calloc(5, sizeof(int*)); 
    for(i = 0; i < S_size; i++){
      fscanf("%d", &S_cost[i]);
      } 
    for(i = 0; i < S_size; i++){
        for(j = 0; j < S_size; j++){
          fscanf("%d", &S[i][j]);  
          }
    }
 
 free(S_cost);
  
  
  fclose(fp);
  return 0;
}

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#21

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:
bitter_fox さんが書きました: まずはS_costについて読み込んで、
その読み込みが終わってからS[j]について読み込みましょう。

コード:

    for(i = 0; i < S_size; i++){
        for(j = 0; j < S_size; j++){
          fscanf("%d", &S[i][j]);  
          }
    }
こうすればS_costを読み込んだ後改めてSを読み込むのでしょうか?
そうですね、j < S_sizeがj < E_sizeだという点を除いては出来ています。
ファイブマン さんが書きました: それから、メモリを確保した後、free()で逃がす作業もやらなくてはいけないのですか。

コード:

    S_cost = (int*)calloc(5, sizeof(int)); 
   S = (int**)calloc(5, sizeof(int*)); 
freeで解放する作業は行わなければなりませんが、多くの場合プログラムが終了するとOSが解放してくれるので今回の場合は行わなくても結構です。
余裕があればやってみてください。

既にお分かりかと思いますが5はS_sizeですね。
S_cost[0]~S_cost[S_size-1]とS[0]~S[S_size-1]の確保は出来ましたが、S[0]~S[S_size-1]のそれぞれについてもE_size個分int型の要素を確保しなければなりません。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#22

投稿記事 by ファイブマン » 14年前

回答ありがとうございます。
bitter_fox さんが書きました: S[0]~S[S_size-1]のそれぞれについてもE_size個分int型の要素を確保しなければなりません。

コード:

 for(i = 0; i < S_size; i++){
        for(j = 0; j < E_size; j++){
          fscanf("%d", &S[i][j]);  
          S[i] = (int)calloc(E_size[j], sizeof(int));
          }
    } 
以上のようにしてみたのですがどこか違うような気がします。
どこが間違っているのでしょうか。
回答よろしくお願いします。

コード:

#include <stdio.h>
#include <stdlib.h>
#define COST 5
 
int main(void)
{
  FILE *fp;
  int **array = (int**)malloc(sizeof(int*));  /* ポインタの配列を割り当てる */
  int i, j, n;
  int **S, *S_cost;
  int S_size, E_size;
  
  fp = fopen("example_a.txt", "r");
  if(fp == NULL)
    exit(0);
  
  fscanf(fp, "%d%d", &S_size, &E_size);
  fscanf(fp, "%d",S);
    **S = S_size*sizeof(int*);
    *S_cost = S_size*sizeof(int*); 
    S_cost = (int*)calloc(5, sizeof(int)); 
   S = (int**)calloc(5, sizeof(int*)); 
    for(i = 0; i < S_size; i++){
      fscanf("%d", &S_cost[i]);
      } 
    for(i = 0; i < S_size; i++){
        for(j = 0; j < E_size; j++){
          fscanf("%d", &S[i][j]);  
          S[i] = (int)calloc(E_size[j], sizeof(int));
          }
    } 

  fclose(fp);
  return 0;
}

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#23

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:
bitter_fox さんが書きました: S[0]~S[S_size-1]のそれぞれについてもE_size個分int型の要素を確保しなければなりません。

コード:

 for(i = 0; i < S_size; i++){
        for(j = 0; j < E_size; j++){
          fscanf("%d", &S[i][j]);  
          S[i] = (int)calloc(E_size[j], sizeof(int));
          }
    } 
E_sizeは配列ではなくint型の変数なのでE_size[j]のようなアクセスは通常はしませんよね?
それからSはint*型なのにint型にキャストして代入するのは正しいですか?
S[j]に値を取得してから確保してますね。C言語で直に処理を理解するのが難しいのであれば一度日本語にしてみてください。問題があることがすぐに分かるかと思います

コード:

// この時点ではS[n][m]は未確保の領域(0 <= n < S_size, 0 <= m < E_size)
 for(i = 0; i < S_size; i++){ // 0~S_sizeまでループ(S_size含まず)
        for(j = 0; j < E_size; j++){ // 0~E_sizeまでループ(E_size含まず)
          fscanf("%d", &S[i][j]);  // ファイルから値を読み込みS[i][j]に代入
          S[i] = (int)calloc(E_size, sizeof(int)); // S[i]にint型E_size個確保
          }
    } 
読み込みとほぼ同時に確保するのも結構ですが、混乱を避けるために
  S = (int**)calloc(5, sizeof(int*));
の直後に確保してみてはいかがでしょう?

読み込みに成功したら前のプログラムを修正します。

コード:

#include<stdio.h>
#include<stdlib.h>

#define S_SIZE 8
#define E_SIZE 9

double calc(int S[E_SIZE], int S_cost){
  int e, count = 0;
  
  // 有効な探査対象の個数を探す(a[e]が1の物)
  for (e = 0; e < E_SIZE; e++){
    if (S[e] == 1){
      count++;
    }
  }
  if (count == 0){
    return -1;
  }
  return ((double)S_cost) / count;
}
 
int main(void){
  
  int S_cost[] = {90, 34, 23, 30, 20, 98, 100, 2};
  int i, j,k, min_n;  
  double min_cost, cost_buf;
  int S[S_SIZE][E_SIZE] = {
    {0, 0, 1, 1, 1, 1, 0, 0, 0}, 
    {0, 0, 1, 0, 0, 0, 0, 0, 0},
    {1, 1, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 1, 0, 1, 0, 0},
    {0, 0, 0, 0, 1, 1, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 1, 0},
    {1, 1, 1, 0, 0, 0, 0, 1, 1},
    {0, 0, 0, 0, 0, 0, 0, 0, 1}
  };
  
  for(k = 0; k < S_SIZE; k++){
    min_n = -1;    
    for(i = 0; i < S_SIZE; i++){
      cost_buf = calc(S[i], S_cost[i]);
      // printf("[%d]:%lf\n",i+1,cost_buf);
      if (cost_buf != -1)
    {
      if(min_n == -1){  
        min_cost = cost_buf;
        min_n = i;      
      }
      else{ 
        if(cost_buf < min_cost){
          min_cost = cost_buf;
          min_n = i;  
        }
      }
    } 
    }
  if(min_n == -1)
      break;
    printf("Siの添字iは%d, その時のコストは%d\n", (min_n)+1, S_cost[min_n]);
    for(i =0; i < E_SIZE; i++){
      if((S[min_n][i]) == 1)
    for(j = 0; j < S_SIZE; j++){
      if((S[j][i]) == 1)     
        S[j][i] = -1;    
    } 
    }    
  }
  return 0;
}
この様な感じになっていたと思います。
これらのS_SIZEとE_SIZEが変数S_sizeとE_sizeに変わります。
そしてcalc関数の第一引数がS[E_SIZE]の様に配列になっていましたがmain内でSは配列ではなくポインタで扱われますのでそれに合わせてint*型になるように変更します。
それに合わせて要素数を別途引数で受け取るように変更します。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#24

投稿記事 by ファイブマン » 14年前

コード:


S = (int**)calloc(5, sizeof(int));  
  
//// 

for(i = 0; i < S_size; i++){
    fscanf("%d", &S_cost[i]);  //c.26
  } 
  for(i = 0; i <= S_size; i++){
    for(j = 0; j <= E_size; j++){
      fscanf("%d", &S[i][j]);    //c.30
    }
  } 
  
少し変えてみたのですが,
コンパイルエラー
q.c: In function `main':
q.c:26: 警告: 互換性のないポインタ型からの引数 1 個の `fscanf' を渡しますです
q.c:26: 警告: 互換性のないポインタ型からの引数 2 個の `fscanf' を渡しますです
q.c:30: 警告: 互換性のないポインタ型からの引数 1 個の `fscanf' を渡しますです
q.c:30: 警告: 互換性のないポインタ型からの引数 2 個の `fscanf' を渡しますです
が出てしまいました.

このエラーが消えれば指摘した箇所が訂正され,次の作業に移れるのでしょうか.
そしてこのエラーの理由がわかりません.
ご指摘宜しくお願いします.

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#25

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:

コード:


S = (int**)calloc(5, sizeof(int));  
  
//// 

for(i = 0; i < S_size; i++){
    fscanf("%d", &S_cost[i]);  //c.26
  } 
  for(i = 0; i <= S_size; i++){
    for(j = 0; j <= E_size; j++){
      fscanf("%d", &S[i][j]);    //c.30
    }
  } 
  
ファイルポインタfpが渡されていませんね。
http://hitorilife.com/fscanf.php

それから5ではなくS_sizeを使っておかないとデータを変えたときに正しく動かないですよ

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#26

投稿記事 by ファイブマン » 14年前

bitter_fox さんが書きました: ファイルポインタfpが渡されていませんね。

コード:

for(i = 0; i < S_size; i++){
    fscanf(fp, "%d", &S_cost[i]);
  } 
  for(i = 0; i <= S_size; i++){
    for(j = 0; j <= E_size; j++){
      fscanf(fp, "%d", &S[i][j]);  
    }
  } 
こうしたのですがコンパイルをし,実行したらセグメントエラーが出たのですがこれあはどうしてでしょうか.
回答宜しくお願いします.

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#27

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました: こうしたのですがコンパイルをし,実行したらセグメントエラーが出たのですがこれあはどうしてでしょうか.
S[0]~S[S_size-1]のそれぞれについてメモリを確保していますか?

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#28

投稿記事 by ファイブマン » 14年前

コード:

 S[i] = (int*)calloc(S_size, sizeof(int));
  S[j] = (int*)calloc(E_size, sizeof(int));
こうなる手はずでしょうか?それでもまだセグメントエラーが出てしまうのですが...

コード:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  FILE *fp;
  int **array = (int**)malloc(sizeof(int*));  /* ポインタの配列を割り当てる */
  int i, j, n;
  int **S, *S_cost;
  int S_size, E_size;
  
  fp = fopen("example_a.txt", "r");
  if(fp == NULL)
    exit(0);
  
  fscanf(fp, "%d%d", &S_size, &E_size);
  fscanf(fp, "%d",S);
  **S = S_size*sizeof(int*); 
  S[i] = (int*)calloc(S_size, sizeof(int));
  S[j] = (int*)calloc(E_size, sizeof(int));
  *S_cost = S_size*sizeof(int*); 
  S_cost = (int*)calloc(S_size, sizeof(int)); 
  S = (int**)calloc(5, sizeof(int));  
  
  for(i = 0; i < S_size; i++){
    fscanf(fp, "%d", &S_cost[i]);
  } 
  for(i = 0; i <= S_size; i++){
    for(j = 0; j <= E_size; j++){
      fscanf(fp, "%d", &S[i][j]);  
    }
  } 
    fclose(fp);
    return 0;
}


アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#29

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:

コード:

 S[i] = (int*)calloc(S_size, sizeof(int));
  S[j] = (int*)calloc(E_size, sizeof(int));
こうなる手はずでしょうか?それでもまだセグメントエラーが出てしまうのですが...
まず日本語で考えてみましょう。
例えば次のような感じです。

コード:

int*型の要素をS_size個分確保 ⇒ Sに代入
S[0]~S[S_size]のそれぞれについて、
int型の要素をE_size個分確保 ⇒S[i]に代入(iはループ変数)
日本語で考えられたらそれをC言語に落としていってください。
ファイブマン さんが書きました:

コード:

  fscanf(fp, "%d",S);
これは不要です。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#30

投稿記事 by ファイブマン » 14年前

bitter_fox さんが書きました:

コード:

int*型の要素をS_size個分確保 ⇒ Sに代入
S[0]~S[S_size]のそれぞれについて、
int型の要素をE_size個分確保 ⇒S[i]に代入(iはループ変数)
に対して

コード:

S = (int**)calloc(S_size, sizeof(int*);  
  for(i = 0; i < S_size; i++){
   S[i] = (int*)calloc(E_size, sizeof(int));
こうなるのでしょうか.
これでもセグメントエラーになるのですが,つまりは間違っているということでしょうか.
それともまたべつに誤りがあるということでしょうか.
何度もすみません,回答宜しくお願いします.

コード:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  FILE *fp;
  int **array = (int**)malloc(sizeof(int*));  /* ポインタの配列を割り当てる */
  int i, j, n;
  int **S, *S_cost;
  int S_size, E_size;
  
  fp = fopen("example_a.txt", "r");
  if(fp == NULL)
    exit(0);
  
  fscanf(fp, "%d%d", &S_size, &E_size);
  **S = S_size*sizeof(int*); 
  *S = (int*)calloc(S_size, sizeof(int));
  *S_cost = S_size*sizeof(int*); 
  S_cost = (int*)calloc(S_size, sizeof(int)); 
  S = (int**)calloc(S_size, sizeof(int*));  
  
  for(i = 0; i < S_size; i++){
    S[i] = (int*)calloc(E_size, sizeof(int));
    fscanf(fp, "%d", &S_cost[i]);
  } 
  for(i = 0; i <= S_size; i++){
    for(j = 0; j <= E_size; j++){
      fscanf(fp, "%d", &S[i][j]);  
    }
  } 
  fclose(fp);
    return 0;
}



アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#31

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました: に対して

コード:

S = (int**)calloc(S_size, sizeof(int*);  
  for(i = 0; i < S_size; i++){
   S[i] = (int*)calloc(E_size, sizeof(int));
こうなるのでしょうか.
そうですね、そのようになります。
ファイブマン さんが書きました: これでもセグメントエラーになるのですが,つまりは間違っているということでしょうか.
それともまたべつに誤りがあるということでしょうか.

コード:

  **S = S_size*sizeof(int*); 
  *S_cost = S_size*sizeof(int*); 
  
  for(i = 0; i <= S_size; i++){
    for(j = 0; j <= E_size; j++){
      fscanf(fp, "%d", &S[i][j]);  
    }
  } 

まず、上二行は不要です。
それからi <= S_sizeとj <= E_sizeだと確保した領域の外を参照してしまいますよ。

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#32

投稿記事 by ファイブマン » 14年前

ご指摘ありがとうございます。次は前に書いたグリーディー法のプログラムに上手く組み込むわけですね。できるところまでやってみたのですがどこを上手く組みかえればいいかわかりません。またコンパイラの調子が悪くなり、コンパイラが使えない状況になってしまいました。
ご回答よろしくお願いします。

コード:


#include<stdio.h>
#include<stdlib.h>
 

double calc(int*S, int S_cost){
  int e, count = 0;
  
  // 有効な探査対象の個数を探す(a[e]が1の物)
  for (e = 0; e < &E_size; e++){
    if (&S[e] == 1){
      count++;
    }
  }
  if (count == 0){
    return -1;
  }
  return ((double)S_cost) / count;
}
 
int main(void){
  
  int S_cost*;
  int i, j,k, min_n;  
  double min_cost, cost_buf;
  int S**=fscanf(fp, "%d", &S[i][j]); ;
  
  for(k = 0; k < S_size; k++){
    min_n = -1;    
    for(i = 0; i < S_size; i++){
      cost_buf = calc(S*, S_cost[i]);
      if (cost_buf != -1)
    {
      if(min_n == -1){  
        min_cost = cost_buf;
        min_n = i;      
      }
      else{ 
        if(cost_buf < min_cost){
          min_cost = cost_buf;
          min_n = i;  
        }
      }
    } 
    }
  if(min_n == -1)
      break;
    printf("Siの添字iは%d, その時のコストは%d\n", (min_n)+1, S_cost[min_n]);
    for(i =0; i < E_size; i++){
      if((S[min_n][i]) == 1)
    for(j = 0; j < S_size; j++){
      if((S[j][i]) == 1)     
        S[j][i] = -1;    
    } 
    }    
  }
  return 0;
}

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#33

投稿記事 by bitter_fox » 14年前

ファイブマン さんが書きました:ご指摘ありがとうございます。次は前に書いたグリーディー法のプログラムに上手く組み込むわけですね。できるところまでやってみたのですがどこを上手く組みかえればいいかわかりません。またコンパイラの調子が悪くなり、コンパイラが使えない状況になってしまいました。
http://ideone.com/ 等インターネット上のコンパイラサービスもありますのでそちらも利用してください。

問題のある点をコメントしておきました。
ファイブマン さんが書きました:

コード:


#include<stdio.h>
#include<stdlib.h>
 

double calc(int*S, int S_cost){
  int e, count = 0;
  
  // 有効な探査対象の個数を探す(a[e]が1の物)
  for (e = 0; e < &E_size; e++){ // E_sizeはここからは見えない
    if (&S[e] == 1){ // アドレスと1を比較している
      count++;
    }
  }
  if (count == 0){
    return -1;
  }
  return ((double)S_cost) / count;
}
 
int main(void){
  
  int S_cost*;
  int i, j,k, min_n;  
  double min_cost, cost_buf;
  int S**=fscanf(fp, "%d", &S[i][j]); ; // S**は変、さっき作ったプログラムが読み込む処理なのにfscanf(fp, "%d", &S[i][j])を使っている(当然これでは読み込めない)
  
  for(k = 0; k < S_size; k++){
    min_n = -1;    
    for(i = 0; i < S_size; i++){
      cost_buf = calc(S*, S_cost[i]);
      if (cost_buf != -1)
    {
      if(min_n == -1){  
        min_cost = cost_buf;
        min_n = i;      
      }
      else{ 
        if(cost_buf < min_cost){
          min_cost = cost_buf;
          min_n = i;  
        }
      }
    } 
    }
  if(min_n == -1)
      break;
    printf("Siの添字iは%d, その時のコストは%d\n", (min_n)+1, S_cost[min_n]);
    for(i =0; i < E_size; i++){
      if((S[min_n][i]) == 1)
    for(j = 0; j < S_size; j++){
      if((S[j][i]) == 1)     
        S[j][i] = -1;    
    } 
    }    
  }
  return 0;
}

ファイブマン

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#34

投稿記事 by ファイブマン » 14年前

すみません.〆切があと2時間ほどになってしまったので,ここまで教えていただいて申し訳ないのですが,解答を示してくれないでしょうか.課題を提出できた後,また詳しく研究したいと思いますのでお願いできますでしょうか.
宜しくお願いします.

コード:

#include<stdlib.h>
 
 
double calc(int*S, int S_cost){
 FILE *fp;
  int e, count = 0;
  int S_size, E_size;
  S = (int**)calloc(S_size, sizeof(int*));  
fscanf(fp, "%d,%d", &S_size, &E_size);
  // 有効な探査対象の個数を探す(a[e]が1の物)
  for (e = 0; e < &E_size; e++){
    if (*S[e] == 1){
      count++;
    }
  }
  if (count == 0){
    return -1;
  }
  return ((double)S_cost) / count;
}
 
int main(void){
  FILE *fp;
  int S_cost*;
  int i, j,k, min_n;  
  double min_cost, cost_buf;
  int **S, *S_cost;
  int S_size, E_size;
  
fp = fopen("example_a.txt", "r");
  if(fp == NULL)
    exit(0);
  
    exit(0);
  
  fscanf(fp, "%d%d", &S_size, &E_size);
  *S = (int*)calloc(S_size, sizeof(int));
  S_cost = (int*)calloc(S_size, sizeof(int)); 
  S = (int**)calloc(S_size, sizeof(int*));  
  
  for(i = 0; i < S_size; i++){
    S[i] = (int*)calloc(E_size, sizeof(int));
    fscanf(fp, "%d", &S_cost[i]);
  } 
  for(i = 0; i < S_size; i++){
    for(j = 0; j < E_size; j++){
      fscanf(fp, "%d", &S[i][j]);  
    }
  } 
  fclose(fp);
    return 0;
}



  for(k = 0; k < S_size; k++){
    min_n = -1;    
    for(i = 0; i < S_size; i++){
      cost_buf = calc(S*, S_cost[i]);
      if (cost_buf != -1)
    {
      if(min_n == -1){  
        min_cost = cost_buf;
        min_n = i;      
      }
      else{ 
        if(cost_buf < min_cost){
          min_cost = cost_buf;
          min_n = i;  
        }
      }
    } 
    }
    if(min_n == -1)
      break;
    printf("Siの添字iは%d, その時のコストは%d\n", (min_n)+1, S_cost[min_n]);
    for(i =0; i < E_size; i++){
      if((S[min_n][i]) == 1)
    for(j = 0; j < S_size; j++){
      if((S[j][i]) == 1)     
        S[j][i] = -1;    
    } 
    }    
  }
  return 0;
}

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#35

投稿記事 by beatle » 14年前

すべてのレスを丁寧に読んだわけではありませんが、「配列の配列」を作る方法で悩んでいるみたいです。
そのやり方を、少し違った切り口で書いてみたいと思います。

まず、NxMの要素を持つint型の配列の配列を作るコードは以下のようになります。

コード:

typedef int*     array_t; // 「int*」に、「array_t」という名前を付ける。array_tは「配列型」という意味。
typedef array_t* array_of_array_t; // 「array_t*」に、「array_of_array_t」という名前を付ける。array_of_array_tは「配列の配列型」という意味。

array_of_array_t array_of_array; // 「配列の配列型」の変数を作る

array_of_array = (array_of_array_t)calloc(N, sizeof(array_t)); // 「配列の配列」の実体を作る

for (int i = 0; i < N; ++i)
{
    array_of_array[i] = (array_t)calloc(M, sizeof(int)); // 「配列」の実体を作る
}
typedefは、既存の型に別名を付けます。
2行のtypedefで、次のような別名を付けました。
  • int* => array_t
  • array_t* => array_or_array_t
array_tは int* の別名ですから、array_of_array_tは int** の別名でもあります。


さて、callocを用いて配列を生成する基本はこうですね。

コード:

// foo個の要素を持つ、bar型の配列を作る
(bar*)calloc(foo, sizeof(bar))
実際には

コード:

(array_of_array_t)calloc(N, sizeof(array_t))
ですから、array_of_arrayはN個の要素を持つ、array_t型の配列ですね。
つまりarray_of_arrayの中身はこんな風になっています。

コード:

0: [array_t型変数]
1: [array_t型変数]
...
N-1: [array_t型変数]
また、forの中で

コード:

array_of_array[i] = (array_t)calloc(M, sizeof(int));
とありますので、array_of_arrayはM個の要素を持つ、int型の配列です。
つまり各々のarray_of_arrayの中身はこんな風になっています。

コード:

0: [int型変数]
1: [int型変数]
...
M-1: [int型変数]

これまで見てきたように、配列の配列を作るには
  1. 「ポインタの配列」を作って
  2. 各々のポインタに、配列を設定する
のです。


コレをSに応用してみましょう。

コード:

// S_size, E_sizeを適切な値にしておく
typedef int* array_t; // 「int*」に、「array_t」という名前を付ける。
typedef array_t* array_of_array_t; // 「array_t*」に、「array_of_array_t」という名前を付ける。

array_of_array_t S; // 「配列の配列型」の変数を作る

S = (array_of_array_t)calloc(S_size, sizeof(array_t)); // 「配列の配列」の実体を作る

for (int i = 0; i < S_size; ++i)
{
    S[i] = (array_t)calloc(E_size, sizeof(int)); // 「配列」の実体を作る
}
これで、SはS_size x E_sizeの大きさを持つ2次元配列になりました。
以降は S[j] でアクセスできます。

長文失礼しました。

No: 34を動作するようにしてみたhttp://ideone.com/rQjnP

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: またグリーディー法の問題なのですが少し形式が違い,わからなくなってしまいました.

#36

投稿記事 by bitter_fox » 14年前

動くものは既にbeatleさんが書かれているので、それに前回からの変更点の要約をコメントしておきましたので参考にしてください。
http://ideone.com/BG7h6

閉鎖

“C言語何でも質問掲示板” へ戻る