回答編集履歴

2

ソースを追加

2021/01/20 09:52

投稿

ppaul
ppaul

スコア24666

test CHANGED
@@ -41,3 +41,433 @@
41
41
  しかし、2メディアンであれば、最適解はAとEになりますね。
42
42
 
43
43
  これはどうやって求めれば良いのかというアルゴリズムが分からないので、もう少し詳しく書いてもらえませんか。
44
+
45
+
46
+
47
+ ---------------------------------------------------------------
48
+
49
+ YATさんが期待するのは以下のプログラムでよろしいですか。
50
+
51
+ 関数分割をしたとき、本来であれば1次元配列に変えて受け渡しをするべきなのですが、そこまでやる気力がなく、外部変数とさせていただきました。変数名や関数名も間に合わせですみません。
52
+
53
+ また、k=1とk>2を同じアルゴリズムで書くために無限大を使っています。こういう使い方については賛否両論あるだろうとは思います。
54
+
55
+
56
+
57
+ ```C
58
+
59
+ #include <stdio.h>
60
+
61
+ #include <stdlib.h>
62
+
63
+ #include <math.h>
64
+
65
+ #define FNLEN (50)
66
+
67
+ #define MAX_N (100)
68
+
69
+ #define NOTSELECTED (0)
70
+
71
+ #define SELECTED (1)
72
+
73
+
74
+
75
+ double dem[MAX_N]; //重み
76
+
77
+ double dist[MAX_N][MAX_N]; //距離
78
+
79
+ double wdist[MAX_N][MAX_N]; //重み付き距離
80
+
81
+ double wdistk[MAX_N][MAX_N]; //k番目の重み付き距離
82
+
83
+ double wsum[MAX_N]; //重み付き距離合計
84
+
85
+ double mindist[MAX_N]; //重みの最小値
86
+
87
+ int selected[MAX_N]; //既に選ばれた列
88
+
89
+ int nnode; // ノード数
90
+
91
+
92
+
93
+ void read_data(void) {
94
+
95
+ FILE *fp;
96
+
97
+ int i, j;
98
+
99
+ char file_name[FNLEN];
100
+
101
+
102
+
103
+ printf("Data file name: "); scanf("%s", file_name);
104
+
105
+ if ((fp = fopen(file_name,"r")) == NULL){
106
+
107
+ printf("%s: ファイルをオープンできません!\n", file_name);
108
+
109
+ exit(-1);
110
+
111
+ }
112
+
113
+
114
+
115
+ printf("データファイル名: %s\n", file_name);
116
+
117
+ fscanf(fp,"%d",&nnode);
118
+
119
+ if (nnode < 1 || nnode > MAX_N) {
120
+
121
+ printf("ノードの数は1以上%3d以下にしてください!\n", MAX_N);
122
+
123
+ exit(-1);
124
+
125
+ }
126
+
127
+
128
+
129
+ for (i = 0; i < nnode; i++){
130
+
131
+ fscanf(fp, "%lf", &dem[i]);
132
+
133
+ }
134
+
135
+ for (i = 0; i < nnode; i++){
136
+
137
+ for (j = 0; j < nnode; j++){
138
+
139
+ fscanf(fp, "%lf", &dist[i][j]);
140
+
141
+ }
142
+
143
+ }
144
+
145
+ fclose(fp);
146
+
147
+ return;
148
+
149
+ }
150
+
151
+
152
+
153
+ void initialize(void) {
154
+
155
+ int i;
156
+
157
+ for (i=0; i<nnode; i++) {
158
+
159
+ mindist[i] = INFINITY;
160
+
161
+ selected[i] = NOTSELECTED;
162
+
163
+ }
164
+
165
+ }
166
+
167
+
168
+
169
+ void cal_wdist(void) {
170
+
171
+ int i, j;
172
+
173
+
174
+
175
+ for (i = 0; i < nnode; i++) {
176
+
177
+ for (j = 0; j < nnode; j++) {
178
+
179
+ wdist[i][j] = dem[i] * dist[i][j];
180
+
181
+ }
182
+
183
+ }
184
+
185
+ return;
186
+
187
+ }
188
+
189
+
190
+
191
+ void print_double(double d) {
192
+
193
+ if (d == INFINITY) {
194
+
195
+ printf(" - ");
196
+
197
+ }
198
+
199
+ else {
200
+
201
+ printf("%5.1f ", d);
202
+
203
+ }
204
+
205
+ }
206
+
207
+
208
+
209
+ void print_wdistk(int k, int select) {
210
+
211
+ int i, j;
212
+
213
+
214
+
215
+ printf(" ");
216
+
217
+ for (i=0; i < nnode; i++) {
218
+
219
+ printf(" N%03d ", i+1);
220
+
221
+ }
222
+
223
+ printf("\n");
224
+
225
+
226
+
227
+ for (i = 0; i < nnode; i++) {
228
+
229
+ printf("N%03d ", i+1);
230
+
231
+ for (j = 0; j < nnode; j++) {
232
+
233
+ print_double(wdistk[i][j]);
234
+
235
+ }
236
+
237
+ printf("\n");
238
+
239
+ }
240
+
241
+ printf("合計 ");
242
+
243
+ for (j = 0; j < nnode; j++) {
244
+
245
+ print_double(wsum[j]);
246
+
247
+ }
248
+
249
+ printf("\n\nk=%dの最小値の列番号は %dで、その合計は ", k, select + 1);
250
+
251
+ print_double(wsum[select]);
252
+
253
+ printf("\n\n\n");
254
+
255
+ return;
256
+
257
+ }
258
+
259
+
260
+
261
+ int cal_wdistk(void) {
262
+
263
+ int i, j;
264
+
265
+ int min_index = 0;
266
+
267
+
268
+
269
+ for (j = 0; j < nnode; j++) {
270
+
271
+ for (i = 0; i < nnode; i++) {
272
+
273
+ if (selected[j] == SELECTED) {
274
+
275
+ wdistk[i][j] = INFINITY;
276
+
277
+ }
278
+
279
+ else if (wdist[i][j] < mindist[i]) {
280
+
281
+ wdistk[i][j] = wdist[i][j];
282
+
283
+ }
284
+
285
+ else {
286
+
287
+ wdistk[i][j] = mindist[i];
288
+
289
+ }
290
+
291
+ }
292
+
293
+ }
294
+
295
+ for (j = 0; j < nnode; j++) {
296
+
297
+ wsum[j] = 0.0;
298
+
299
+ for (i = 0; i < nnode; i++) {
300
+
301
+ wsum[j] += wdistk[i][j];
302
+
303
+ }
304
+
305
+ }
306
+
307
+ for (j = 1; j < nnode; j++) {
308
+
309
+ if (wsum[min_index] > wsum[j]) {
310
+
311
+ min_index = j;
312
+
313
+ }
314
+
315
+ }
316
+
317
+ return min_index;
318
+
319
+ }
320
+
321
+
322
+
323
+ void update(int select) {
324
+
325
+ int j;
326
+
327
+
328
+
329
+ selected[select] = SELECTED;
330
+
331
+ for (j=0; j < nnode; j++) {
332
+
333
+ if (wdist[j][select] < mindist[j]) {
334
+
335
+ mindist[j] = wdist[j][select];
336
+
337
+ }
338
+
339
+ }
340
+
341
+ }
342
+
343
+
344
+
345
+ int main()
346
+
347
+ {
348
+
349
+ int k, select;
350
+
351
+
352
+
353
+ read_data();
354
+
355
+ initialize();
356
+
357
+ cal_wdist();
358
+
359
+
360
+
361
+ for (k=1; k < nnode; k++) {
362
+
363
+ select = cal_wdistk();
364
+
365
+ print_wdistk(k, select);
366
+
367
+ update(select);
368
+
369
+ }
370
+
371
+
372
+
373
+ return 0;
374
+
375
+ }
376
+
377
+ ```
378
+
379
+
380
+
381
+ 出力例は以下です。
382
+
383
+
384
+
385
+ ```shell
386
+
387
+ データファイル名: b.txt
388
+
389
+ N001 N002 N003 N004 N005
390
+
391
+ N001 0.0 80.0 120.0 200.0 240.0
392
+
393
+ N002 70.0 0.0 140.0 210.0 245.0
394
+
395
+ N003 9.0 12.0 0.0 6.0 9.0
396
+
397
+ N004 150.0 180.0 60.0 0.0 60.0
398
+
399
+ N005 270.0 315.0 135.0 90.0 0.0
400
+
401
+ 合計 499.0 587.0 455.0 506.0 554.0
402
+
403
+
404
+
405
+ k=1の最小値の列番号は 3で、その合計は 455.0
406
+
407
+
408
+
409
+
410
+
411
+ N001 N002 N003 N004 N005
412
+
413
+ N001 0.0 80.0 - 120.0 120.0
414
+
415
+ N002 70.0 0.0 - 140.0 140.0
416
+
417
+ N003 0.0 0.0 - 0.0 0.0
418
+
419
+ N004 60.0 60.0 - 0.0 60.0
420
+
421
+ N005 135.0 135.0 - 90.0 0.0
422
+
423
+ 合計 265.0 275.0 - 350.0 320.0
424
+
425
+
426
+
427
+ k=2の最小値の列番号は 1で、その合計は 265.0
428
+
429
+
430
+
431
+
432
+
433
+ N001 N002 N003 N004 N005
434
+
435
+ N001 - 0.0 - 0.0 0.0
436
+
437
+ N002 - 0.0 - 70.0 70.0
438
+
439
+ N003 - 0.0 - 0.0 0.0
440
+
441
+ N004 - 60.0 - 0.0 60.0
442
+
443
+ N005 - 135.0 - 90.0 0.0
444
+
445
+ 合計 - 195.0 - 160.0 130.0
446
+
447
+
448
+
449
+ k=3の最小値の列番号は 5で、その合計は 130.0
450
+
451
+
452
+
453
+
454
+
455
+ N001 N002 N003 N004 N005
456
+
457
+ N001 - 0.0 - 0.0 -
458
+
459
+ N002 - 0.0 - 70.0 -
460
+
461
+ N003 - 0.0 - 0.0 -
462
+
463
+ N004 - 60.0 - 0.0 -
464
+
465
+ N005 - 0.0 - 0.0 -
466
+
467
+ 合計 - 60.0 - 70.0 -
468
+
469
+
470
+
471
+ k=4の最小値の列番号は 2で、その合計は 60.0
472
+
473
+ ```

1

書き間違いの修正

2021/01/20 09:52

投稿

ppaul
ppaul

スコア24666

test CHANGED
@@ -38,6 +38,6 @@
38
38
 
39
39
 
40
40
 
41
- しかし、メディアンであれば、最適解はAとEになりますね。
41
+ しかし、メディアンであれば、最適解はAとEになりますね。
42
42
 
43
43
  これはどうやって求めれば良いのかというアルゴリズムが分からないので、もう少し詳しく書いてもらえませんか。