回答編集履歴

5

ミスの修正

2020/04/27 19:34

投稿

namnium1125
namnium1125

スコア2045

test CHANGED
@@ -138,7 +138,7 @@
138
138
 
139
139
  /*
140
140
 
141
- もしa[i]を合計値に入れずに目的の値になったならば、真を返す。
141
+ もしa[i]を合計値に入れ目的の値になったならば、真を返す。
142
142
 
143
143
  */
144
144
 

4

返答していなかった質問への返答

2020/04/27 19:34

投稿

namnium1125
namnium1125

スコア2045

test CHANGED
@@ -84,408 +84,426 @@
84
84
 
85
85
  ★何をもってdfs(i+1,sum)の値が決まるのかがこの式から読めません。
86
86
 
87
+
88
+
89
+ まず動くソースコードを。コメント、つけ直してみました(大して変わってないかも)
90
+
91
+ ○1, ○2, ○3, ○4はソースコード以下の説明と対応しています。
92
+
93
+
94
+
95
+ wandbox: [https://wandbox.org/permlink/AMrTofmWNM2RKDpA](https://wandbox.org/permlink/AMrTofmWNM2RKDpA)
96
+
97
+
98
+
99
+ ```cpp
100
+
101
+ #include <iostream>
102
+
103
+
104
+
105
+ const int MAX_N = 20;
106
+
107
+ int *a;
108
+
109
+ int n, k;
110
+
111
+
112
+
113
+ bool dfs(int i, int sum) {
114
+
115
+ /*
116
+
117
+ この再帰関数の深さがn(今回は4)であれば、最終的に合計値(sum)が目的の値(k...今回なら13)
118
+
119
+ になっているかを返して終わり。
120
+
121
+ */
122
+
123
+ if (i == n) return sum == k; // ○1
124
+
125
+
126
+
127
+ /*
128
+
129
+ まだ深さが4ではないときに以下は実行される。
130
+
131
+ もしa[i]を合計値に入れずに目的の値になったならば、真を返す。
132
+
133
+ */
134
+
135
+ if (dfs(i + 1, sum)) return true; // ○2
136
+
137
+
138
+
139
+ /*
140
+
141
+ もしa[i]を合計値に入れずに目的の値になったならば、真を返す。
142
+
143
+ */
144
+
145
+ if (dfs(i + 1, sum + a[i])) return true; // ○3
146
+
147
+
148
+
149
+ /*
150
+
151
+ a[i]を入れようが入れまいが、もう合計値にすることは不可能であるからfalseを返す。
152
+
153
+ */
154
+
155
+ return false; // ○4
156
+
157
+ }
158
+
159
+
160
+
161
+ void solve() {
162
+
163
+ if (dfs(0, 0)) printf("Yes\n");
164
+
165
+ else printf("No\n");
166
+
167
+ }
168
+
169
+
170
+
171
+ int main(void) {
172
+
173
+ n = 4;
174
+
175
+ int b[MAX_N] = {1, 2, 4, 7};
176
+
177
+ a = b;
178
+
179
+ k = 13;
180
+
181
+
182
+
183
+ solve(); // Yes
184
+
185
+ }
186
+
187
+ ```
188
+
189
+
190
+
191
+ `i` の役割は配列の何番目の話をしているかで、 `sum` の役割は再帰関数がうまく働くようにするための蓄積値といったところです。
192
+
193
+
194
+
195
+ この関数は次のように動きます。( [https://wandbox.org/permlink/VikAMasmuqES69RS](https://wandbox.org/permlink/VikAMasmuqES69RS) で確認できます。以下の説明文めちゃくちゃ長いですが、実際に動きを追ったほうがわかりやすいので書いてみました。)
196
+
197
+
198
+
199
+ ---
200
+
201
+
202
+
203
+ `dfs(0, 0)`が呼ばれる。
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+ ○1 i ≠ nであるから、まだ値は返さない。
212
+
213
+ ○2 `dfs(1, 0)`が呼ばれる。
214
+
215
+
216
+
217
+
218
+
219
+
220
+
221
+ ○1 i ≠ nであるから、まだ値は返さない。
222
+
223
+ ○2 `dfs(2, 0)`が呼ばれる。
224
+
225
+
226
+
227
+
228
+
229
+
230
+
231
+ ○1 i ≠ nであるから、まだ値は返さない。
232
+
233
+ ○2 `dfs(3, 0)`が呼ばれる。
234
+
235
+
236
+
237
+
238
+
239
+
240
+
241
+ ○1 i ≠ nであるから、まだ値は返さない。
242
+
243
+ ○2 `dfs(4, 0)`が呼ばれる。
244
+
245
+
246
+
247
+
248
+
249
+
250
+
251
+ ○1 i = nであるから、`sum == k` の式の評価値を返す。 `0 == 13` は偽なので、 `dfs(4, 0)` は `false` を返す。
252
+
253
+
254
+
255
+
256
+
257
+
258
+
259
+ ○3 `dfs(3, 0)` の中に戻る。○2 が実行されなかったので、次に `sum(=0)` に `a[3](=7)` が足された
260
+
261
+ `dfs(4, 7)`が呼ばれる。
262
+
263
+
264
+
265
+
266
+
267
+
268
+
269
+ ○1 i = nであるから、`sum == k` の式の評価値を返す。 `7 == 13` は偽なので、 `dfs(4, 7)` は `false` を返す。
270
+
271
+
272
+
273
+
274
+
275
+
276
+
277
+ ○4 `dfs(3, 0)` の中に戻る。 `dfs(3, 0)` は `false` を返す。
278
+
279
+
280
+
281
+
282
+
283
+
284
+
285
+ ○3 `dfs(2, 0)` の中に戻る。○2 が実行されなかったので、次に `sum(=0)` に `a[2](=4)` が足された
286
+
287
+ `dfs(3, 4)`が呼ばれる。
288
+
289
+
290
+
291
+
292
+
293
+
294
+
295
+ ○1 i ≠ nであるから、まだ値は返さない。
296
+
297
+ ○2 `dfs(4, 4)`が呼ばれる。
298
+
299
+
300
+
301
+
302
+
303
+
304
+
305
+ ○1 i = nであるから、`sum == k` の式の評価値を返す。 `4 == 13` は偽なので、 `dfs(4, 4)` は `false` を返す。
306
+
307
+
308
+
309
+
310
+
311
+
312
+
313
+ ○3 `dfs(3, 4)` の中に戻る。○2 が実行されなかったので、次に `sum(=4)` に `a[3](=7)` が足された
314
+
315
+ `dfs(4, 11)`が呼ばれる。
316
+
317
+
318
+
319
+
320
+
321
+
322
+
323
+ ○1 i = nであるから、`sum == k` の式の評価値を返す。 `11 == 13` は偽なので、 `dfs(4, 11)` は `false` を返す。
324
+
325
+
326
+
327
+
328
+
329
+
330
+
331
+ ○4 `dfs(3, 4)` の中に戻る。 `dfs(3, 4)` は `false` を返す。
332
+
333
+
334
+
335
+
336
+
337
+
338
+
339
+ ○4 `dfs(2, 0)` の中に戻る。 `dfs(2, 0)` は `false` を返す。
340
+
341
+
342
+
343
+
344
+
345
+
346
+
347
+ ○3 `dfs(1, 0)` の中に戻る。○2 が実行されなかったので、次に `sum(=0)` に `a[1](=2)` が足された
348
+
349
+ `dfs(2, 2)`が呼ばれる。
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+ ○1 i ≠ nであるから、まだ値は返さない。
358
+
359
+ ○2 `dfs(3, 2)`が呼ばれる。
360
+
361
+
362
+
363
+
364
+
365
+
366
+
367
+ ○1 i ≠ nであるから、まだ値は返さない。
368
+
369
+ ○2 `dfs(4, 2)`が呼ばれる。
370
+
371
+
372
+
373
+
374
+
375
+
376
+
377
+ ○1 i = nであるから、`sum == k` の式の評価値を返す。 `2 == 13` は偽なので、 `dfs(4, 2)` は `false` を返す。
378
+
379
+
380
+
381
+
382
+
383
+
384
+
385
+ ○3 `dfs(3, 2)` の中に戻る。○2 が実行されなかったので、次に `sum(=2)` に `a[3](=7)` が足された
386
+
387
+ `dfs(4, 9)`が呼ばれる。
388
+
389
+
390
+
391
+
392
+
393
+
394
+
395
+ ○1 i = nであるから、`sum == k` の式の評価値を返す。 `9 == 13` は偽なので、 `dfs(4, 9)` は `false` を返す。
396
+
397
+
398
+
399
+
400
+
401
+
402
+
403
+ ○4 `dfs(3, 2)` の中に戻る。 `dfs(3, 2)` は `false` を返す。
404
+
405
+
406
+
407
+
408
+
409
+
410
+
411
+ ○3 `dfs(2, 2)` の中に戻る。○2 が実行されなかったので、次に `sum(=2)` に `a[2](=4)` が足された
412
+
413
+ `dfs(3, 6)`が呼ばれる。
414
+
415
+
416
+
417
+
418
+
419
+
420
+
421
+ ○1 i ≠ nであるから、まだ値は返さない。
422
+
423
+ ○2 `dfs(4, 6)`が呼ばれる。
424
+
425
+
426
+
427
+
428
+
429
+
430
+
431
+ ○1 i = nであるから、`sum == k` の式の評価値を返す。 `6 == 13` は偽なので、 `dfs(4, 6)` は `false` を返す。
432
+
433
+
434
+
435
+
436
+
437
+
438
+
439
+ ○3 `dfs(3, 6)` の中に戻る。○2 が実行されなかったので、次に `sum(=6)` に `a[3](=7)` が足された
440
+
441
+ `dfs(4, 13)`が呼ばれる。
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+ ○1 i = nであるから、`sum == k` の式の評価値を返す。 `13 == 13` は真なので、 `dfs(4, 13)` は `true` を返す。
450
+
451
+
452
+
453
+
454
+
455
+
456
+
457
+ ○3のif文以降が実行される。 `dfs(3, 6)` は `true` を返す。
458
+
459
+
460
+
461
+
462
+
463
+
464
+
465
+ ○3のif文以降が実行される。 `dfs(2, 2)` は `true` を返す。
466
+
467
+
468
+
469
+
470
+
471
+
472
+
473
+ ○3のif文以降が実行される。 `dfs(1, 0)` は `true` を返す。
474
+
475
+
476
+
477
+
478
+
479
+
480
+
481
+ ○2のif文以降が実行される。 `dfs(0, 0)` は `true` を返す。
482
+
483
+
484
+
485
+ ---
486
+
487
+
488
+
489
+ この説明は蟻本p34の解説絵と同じです。
490
+
491
+
492
+
87
493
  ★なぜ0,0なんですか?
88
494
 
89
495
 
90
496
 
91
- 動くソースコードを。コメント、つけ直してみました(大して変ってなかも)
92
-
93
- ○1, ○2, ○3, ○4はソースコード以下の説明と対応しています。
94
-
95
-
96
-
97
- wandbox: [https://wandbox.org/permlink/AMrTofmWNM2RKDpA](https://wandbox.org/permlink/AMrTofmWNM2RKDpA)
98
-
99
-
100
-
101
- ```cpp
102
-
103
- #include <iostream>
104
-
105
-
106
-
107
- const int MAX_N = 20;
108
-
109
- int *a;
110
-
111
- int n, k;
112
-
113
-
114
-
115
- bool dfs(int i, int sum) {
116
-
117
- /*
118
-
119
- この再帰関数の深さがn(今回は4)であれば、最終的に合計値(sum)が目的の値(k...今回なら13)
120
-
121
- になっているかを返して終わり。
122
-
123
- */
124
-
125
- if (i == n) return sum == k; // ○1
126
-
127
-
128
-
129
- /*
130
-
131
- まだ深さが4ではないときに以下は実行される。
132
-
133
- もしa[i]を合計値に入れずに目的の値になったならば、真を返す。
134
-
135
- */
136
-
137
- if (dfs(i + 1, sum)) return true; // ○2
138
-
139
-
140
-
141
- /*
142
-
143
- もしa[i]を合計値に入れずに目的の値になったならば、真を返す。
144
-
145
- */
146
-
147
- if (dfs(i + 1, sum + a[i])) return true; // ○3
148
-
149
-
150
-
151
- /*
152
-
153
- a[i]を入れようが入れまいが、もう合計値にすることは不可能であるからfalseを返す。
154
-
155
- */
156
-
157
- return false; // ○4
158
-
159
- }
160
-
161
-
162
-
163
- void solve() {
164
-
165
- if (dfs(0, 0)) printf("Yes\n");
166
-
167
- else printf("No\n");
168
-
169
- }
170
-
171
-
172
-
173
- int main(void) {
174
-
175
- n = 4;
176
-
177
- int b[MAX_N] = {1, 2, 4, 7};
178
-
179
- a = b;
180
-
181
- k = 13;
182
-
183
-
184
-
185
- solve(); // Yes
186
-
187
- }
188
-
189
- ```
190
-
191
-
192
-
193
- `i` の役割は配列の何番目の話をしているかで、 `sum` の役割は再帰関数がうまく働くようにするための蓄積値といったところです。
194
-
195
-
196
-
197
- この関数は次のように動きます。( [https://wandbox.org/permlink/VikAMasmuqES69RS](https://wandbox.org/permlink/VikAMasmuqES69RS) で確認できます。以下の説明文めちゃくちゃ長いですが、実際に動きを追ったほうがわかりやすいので書いてみました。)
198
-
199
-
200
-
201
- ---
202
-
203
-
204
-
205
- `dfs(0, 0)`が呼ばれる。
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
- ○1 i ≠ nであるから、まだ値は返さない。
214
-
215
- ○2 `dfs(1, 0)`が呼ばれる。
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
- ○1 i ≠ nであるから、まだ値は返さない。
224
-
225
- ○2 `dfs(2, 0)`が呼ばれる。
226
-
227
-
228
-
229
-
230
-
231
-
232
-
233
- ○1 i ≠ nであるから、まだ値は返さない。
234
-
235
- ○2 `dfs(3, 0)`が呼ばれる。
236
-
237
-
238
-
239
-
240
-
241
-
242
-
243
- ○1 i ≠ nであるから、まだ値は返さない。
244
-
245
- ○2 `dfs(4, 0)`が呼ばれる。
246
-
247
-
248
-
249
-
250
-
251
-
252
-
253
- ○1 i = nであるから、`sum == k` の式の評価値を返す。 `0 == 13` は偽なので、 `dfs(4, 0)` は `false` を返す。
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
- ○3 `dfs(3, 0)` の中に戻る。○2 が実行されなかったので、次に `sum(=0)` に `a[3](=7)` が足された
262
-
263
- `dfs(4, 7)`が呼ばれる。
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
- ○1 i = nであるから、`sum == k` の式の評価値を返す。 `7 == 13` は偽なので、 `dfs(4, 7)` は `false` を返す。
272
-
273
-
274
-
275
-
276
-
277
-
278
-
279
- ○4 `dfs(3, 0)` の中に戻る。 `dfs(3, 0)` は `false` を返す。
280
-
281
-
282
-
283
-
284
-
285
-
286
-
287
- ○3 `dfs(2, 0)` の中に戻る。○2 が実行されなかったので、次に `sum(=0)` に `a[2](=4)` が足された
288
-
289
- `dfs(3, 4)`が呼ばれる。
290
-
291
-
292
-
293
-
294
-
295
-
296
-
297
- ○1 i ≠ nであるから、まだ値は返さない。
298
-
299
- ○2 `dfs(4, 4)`が呼ばれる。
300
-
301
-
302
-
303
-
304
-
305
-
306
-
307
- ○1 i = nであるから、`sum == k` の式の評価値を返す。 `4 == 13` は偽なので、 `dfs(4, 4)` は `false` を返す。
308
-
309
-
310
-
311
-
312
-
313
-
314
-
315
- ○3 `dfs(3, 4)` の中に戻る。○2 が実行されなかったので、次に `sum(=4)` に `a[3](=7)` が足された
316
-
317
- `dfs(4, 11)`が呼ばれる。
318
-
319
-
320
-
321
-
322
-
323
-
324
-
325
- ○1 i = nであるから、`sum == k` の式の評価値を返す。 `11 == 13` は偽なので、 `dfs(4, 11)` は `false` を返す。
326
-
327
-
328
-
329
-
330
-
331
-
332
-
333
- ○4 `dfs(3, 4)` の中に戻る。 `dfs(3, 4)` は `false` を返す。
334
-
335
-
336
-
337
-
338
-
339
-
340
-
341
- ○4 `dfs(2, 0)` の中に戻る。 `dfs(2, 0)` は `false` を返す。
342
-
343
-
344
-
345
-
346
-
347
-
348
-
349
- ○3 `dfs(1, 0)` の中に戻る。○2 が実行されなかったので、次に `sum(=0)` に `a[1](=2)` が足された
350
-
351
- `dfs(2, 2)`が呼ばれる。
352
-
353
-
354
-
355
-
356
-
357
-
358
-
359
- ○1 i ≠ nであるから、まだ値は返さない。
360
-
361
- ○2 `dfs(3, 2)`が呼ばれる。
362
-
363
-
364
-
365
-
366
-
367
-
368
-
369
- ○1 i ≠ nであるから、まだ値は返さない。
370
-
371
- ○2 `dfs(4, 2)`が呼ばれる。
372
-
373
-
374
-
375
-
376
-
377
-
378
-
379
- ○1 i = nであるから、`sum == k` の式の評価値を返す。 `2 == 13` は偽なので、 `dfs(4, 2)` は `false` を返す。
380
-
381
-
382
-
383
-
384
-
385
-
386
-
387
- ○3 `dfs(3, 2)` の中に戻る。○2 が実行されなかったので、次に `sum(=2)` に `a[3](=7)` が足された
388
-
389
- `dfs(4, 9)`が呼ばれる。
390
-
391
-
392
-
393
-
394
-
395
-
396
-
397
- ○1 i = nであるから、`sum == k` の式の評価値を返す。 `9 == 13` は偽なので、 `dfs(4, 9)` は `false` を返す。
398
-
399
-
400
-
401
-
402
-
403
-
404
-
405
- ○4 `dfs(3, 2)` の中に戻る。 `dfs(3, 2)` は `false` を返す。
406
-
407
-
408
-
409
-
410
-
411
-
412
-
413
- ○3 `dfs(2, 2)` の中に戻る。○2 が実行されなかったので、次に `sum(=2)` に `a[2](=4)` が足された
414
-
415
- `dfs(3, 6)`が呼ばれる。
416
-
417
-
418
-
419
-
420
-
421
-
422
-
423
- ○1 i ≠ nであるから、まだ値は返さない。
424
-
425
- ○2 `dfs(4, 6)`が呼ばれる。
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
- ○1 i = nであるから、`sum == k` の式の評価値を返す。 `6 == 13` は偽なので、 `dfs(4, 6)` は `false` を返す。
434
-
435
-
436
-
437
-
438
-
439
-
440
-
441
- ○3 `dfs(3, 6)` の中に戻る。○2 が実行されなかったので、次に `sum(=6)` に `a[3](=7)` が足された
442
-
443
- `dfs(4, 13)`が呼ばれる。
444
-
445
-
446
-
447
-
448
-
449
-
450
-
451
- ○1 i = nであるから、`sum == k` の式の評価値を返す。 `13 == 13` は真なので、 `dfs(4, 13)` は `true` を返す。
452
-
453
-
454
-
455
-
456
-
457
-
458
-
459
- ○3のif文以降が実行される。 `dfs(3, 6)` は `true` を返す。
460
-
461
-
462
-
463
-
464
-
465
-
466
-
467
- ○3のif文以降が実行される。 `dfs(2, 2)` は `true` を返す。
468
-
469
-
470
-
471
-
472
-
473
-
474
-
475
- ○3のif文以降が実行される。 `dfs(1, 0)` は `true` を返す。
476
-
477
-
478
-
479
-
480
-
481
-
482
-
483
- ○2のif文以降が実行される。 `dfs(0, 0)` は `true` を返す。
484
-
485
-
486
-
487
- ---
488
-
489
-
490
-
491
- この説明は蟻本p34の解説絵と同じです。遷移についてまだよくわからない部分があれば返信ください。
497
+ dfs関数の再帰の仕組みを理解すれば自かるかと思ます。
498
+
499
+
500
+
501
+ i = 0なのは、配列の0番目から部分和を確認する必要があるためです。これは明白だと思います。(i = 4であればi = 0, 1, 2, 3は無視される...明らかにそれは望んだ操作ではない)
502
+
503
+
504
+
505
+ sum = 0なのは、再帰関数がうまく働くようにするには最初の値を0にする必要があるからというのがわかると思います。この変数は、部分和が目的値になっているかを確認するために使われています。
506
+
507
+
508
+
509
+ 遷移について等、まだよくわからない部分があれば返信ください。m(_ _)m

3

ミスの修正

2020/04/27 19:12

投稿

namnium1125
namnium1125

スコア2045

test CHANGED
@@ -28,7 +28,7 @@
28
28
 
29
29
 
30
30
 
31
- `i`に1が入っていれば、上から順に `2`、 `4`、`1` 、`2`、 `1` の値に置き換わります。
31
+ `i`に1が入っていれば、上から順に `2`、 `4`、`1` 、`1`、 `2` の値に置き換わります。
32
32
 
33
33
 
34
34
 

2

リンクをクリックできるように修正

2020/04/27 19:07

投稿

namnium1125
namnium1125

スコア2045

test CHANGED
@@ -94,7 +94,7 @@
94
94
 
95
95
 
96
96
 
97
- wandbox: https://wandbox.org/permlink/AMrTofmWNM2RKDpA
97
+ wandbox: [https://wandbox.org/permlink/AMrTofmWNM2RKDpA](https://wandbox.org/permlink/AMrTofmWNM2RKDpA)
98
98
 
99
99
 
100
100
 
@@ -194,7 +194,7 @@
194
194
 
195
195
 
196
196
 
197
- この関数は次のように動きます。( https://wandbox.org/permlink/VikAMasmuqES69RS で確認できます。以下の説明文めちゃくちゃ長いですが、実際に動きを追ったほうがわかりやすいので書いてみました。)
197
+ この関数は次のように動きます。( [https://wandbox.org/permlink/VikAMasmuqES69RS](https://wandbox.org/permlink/VikAMasmuqES69RS) で確認できます。以下の説明文めちゃくちゃ長いですが、実際に動きを追ったほうがわかりやすいので書いてみました。)
198
198
 
199
199
 
200
200
 

1

勘違いを起こしそうな解説の修正

2020/04/27 19:02

投稿

namnium1125
namnium1125

スコア2045

test CHANGED
@@ -18,6 +18,8 @@
18
18
 
19
19
  2 * 2
20
20
 
21
+ i
22
+
21
23
  i++
22
24
 
23
25
  ++i
@@ -26,7 +28,7 @@
26
28
 
27
29
 
28
30
 
29
- 上から順に `2`、 `4`、 `i+1`、 `i` の値に置き換わります。
31
+ `i`に1が入っていれば、上から順に `2`、 `4`、`1` `2`、 `1` の値に置き換わります。
30
32
 
31
33
 
32
34
 
@@ -34,7 +36,7 @@
34
36
 
35
37
 
36
38
 
37
- if文の引数として渡されるも、この「評価」が行われています。から、以下のような書き方が可能です。
39
+ if文の引数として渡される式に対しても、この「評価」が行われています。変数がくると変数も評価され値が置き換わりま。よって以下のような書き方が可能です。
38
40
 
39
41
 
40
42
 
@@ -48,11 +50,11 @@
48
50
 
49
51
 
50
52
 
51
- bool hoge = 1 == 2;
53
+ bool hoge = 1 == 2; // hogeにfalseが代入される
52
-
53
-
54
-
54
+
55
+
56
+
55
- if (hoge) {
57
+ if (hoge) { // hogeの評価値はfalseなのでelse以降を実行
56
58
 
57
59
  printf("同じ\n");
58
60