回答編集履歴

2

コード追加

2021/03/01 10:23

投稿

fana
fana

スコア11985

test CHANGED
@@ -27,3 +27,223 @@
27
27
  1つ以上のグループがレシピと合うやつだけ
28
28
 
29
29
  を出力すればよい.
30
+
31
+
32
+
33
+ ---
34
+
35
+
36
+
37
+ [追記]
38
+
39
+ 実装してみたけど,「これはひどい」と言いたくなるコードになった…
40
+
41
+ (特に,材料のグループ分け全パターンを探すところがひどい有様)
42
+
43
+
44
+
45
+ ```C++
46
+
47
+ //EnumGroupingPtn()が使う作業関数
48
+
49
+ void EnumPtnWork(
50
+
51
+ const std::vector<unsigned int> &Mat,
52
+
53
+ std::vector< std::vector<unsigned int> > &Result,
54
+
55
+ int idx,
56
+
57
+ const std::vector< unsigned int > &Curr
58
+
59
+ )
60
+
61
+ {
62
+
63
+ if( idx == Mat.size() )
64
+
65
+ { Result.push_back( Curr ); return; }
66
+
67
+
68
+
69
+ for( int i=0; i<Curr.size(); ++i )
70
+
71
+ {
72
+
73
+ std::vector<unsigned int> C = Curr;
74
+
75
+ C[i] |= Mat[idx];
76
+
77
+ EnumPtnWork( Mat, Result, idx+1, C );
78
+
79
+ }
80
+
81
+
82
+
83
+ std::vector<unsigned int> C = Curr;
84
+
85
+ C.push_back( Mat[idx] );
86
+
87
+ EnumPtnWork( Mat, Result, idx+1, C );
88
+
89
+ }
90
+
91
+
92
+
93
+ //材料のグループ分けパターンを全パターン列挙した結果を作る
94
+
95
+ std::vector< std::vector<unsigned int> > EnumGroupingPtn( const std::vector<unsigned int> &Materials )
96
+
97
+ {
98
+
99
+ std::vector< std::vector<unsigned int> > Result;
100
+
101
+ EnumPtnWork( Materials, Result, 0, std::vector<unsigned int>() );
102
+
103
+ return Result;
104
+
105
+ }
106
+
107
+
108
+
109
+ //main
110
+
111
+ int main(void)
112
+
113
+ {
114
+
115
+ //材料の種類要定数:bitパターンで表す
116
+
117
+ const unsigned int Stone = 0x01;
118
+
119
+ const unsigned int Wood = 0x01 << 1;
120
+
121
+ const unsigned int Iron = 0x02 << 2;
122
+
123
+
124
+
125
+ //レシピ
126
+
127
+ // key = 作るのに必要な材料の組み合わせ
128
+
129
+ // value = <成果物の種類を表す定数(bitパターン), 成果物名称>
130
+
131
+ const std::map< unsigned int, std::pair<unsigned int, std::string> > Recipies
132
+
133
+ {
134
+
135
+ { Wood, { 0x1, "椅子" } },
136
+
137
+ { Wood|Iron|Stone, { 0x1<<1, "家" } },
138
+
139
+ { Iron, { 0x1<<2, "剣" } },
140
+
141
+ { Wood|Iron, { 0x1<<3, "ノコギリ" } }
142
+
143
+ };
144
+
145
+
146
+
147
+ //与えられた材料
148
+
149
+ const std::vector<unsigned int> Materials{ Stone, Wood, Iron };
150
+
151
+
152
+
153
+ //結果用データ
154
+
155
+ // vector of < 成果物の組み合わせを示す値, 表示用文字列 >
156
+
157
+ std::vector< std::pair<unsigned int,std::string> > Result;
158
+
159
+
160
+
161
+ {//メインの処理:材料のグループ分け全パターンについて調査する
162
+
163
+ for( const auto &MatGroups : EnumGroupingPtn( Materials ) )
164
+
165
+ {
166
+
167
+ //このグループ分けで作れる成果物群を調査
168
+
169
+ std::string Str_for_Disp; //※これは単なる結果表示用文字列
170
+
171
+ unsigned int CraftPtn = 0;
172
+
173
+ for( unsigned int MG : MatGroups )
174
+
175
+ {
176
+
177
+ auto iRecipie = Recipies.find( MG );
178
+
179
+ if( iRecipie != Recipies.end() )
180
+
181
+ {
182
+
183
+ if( CraftPtn>0 )Str_for_Disp += ", ";
184
+
185
+ Str_for_Disp += iRecipie->second.second;
186
+
187
+
188
+
189
+ CraftPtn |= iRecipie->second.first;
190
+
191
+ }
192
+
193
+ }
194
+
195
+ if( CraftPtn==0 )continue; //何も作れない場合
196
+
197
+
198
+
199
+ //何か作れる場合
200
+
201
+ bool Rejected = false;
202
+
203
+ for( auto i=Result.begin(); i!=Result.end(); /*NOP*/ )
204
+
205
+ {
206
+
207
+ unsigned int And = ( i->first & CraftPtn );
208
+
209
+
210
+
211
+ if( And == CraftPtn ) //既存よりも作れる物が少ない→このパターンを棄却
212
+
213
+ { Rejected=true; break; }
214
+
215
+ else if( And == i->first ) //既存よりもたくさん作れる→既存を棄却
216
+
217
+ { i = Result.erase( i ); }
218
+
219
+ else
220
+
221
+ { ++i; }
222
+
223
+ }
224
+
225
+
226
+
227
+ if( !Rejected ) //棄却されなかったならResultに追加
228
+
229
+ { Result.emplace_back( CraftPtn, Str_for_Disp ); }
230
+
231
+ }
232
+
233
+ }
234
+
235
+
236
+
237
+ //結果表示
238
+
239
+ for( const auto &r : Result )
240
+
241
+ { std::cout << r.second << std::endl; }
242
+
243
+
244
+
245
+ return 0;
246
+
247
+ }
248
+
249
+ ```

1

修正

2021/03/01 10:22

投稿

fana
fana

スコア11985

test CHANGED
@@ -20,4 +20,10 @@
20
20
 
21
21
 
22
22
 
23
+ この中で,
24
+
23
- この中で,全てのグループに見合うレシピがあるやつだけを出力すればよい.
25
+ ~~全てのグループに見合うレシピがあるやつだけ~~
26
+
27
+ 1つ以上のグループがレシピと合うやつだけ
28
+
29
+ を出力すればよい.