teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

コード追加

2021/03/01 10:23

投稿

fana
fana

スコア12227

answer CHANGED
@@ -12,4 +12,114 @@
12
12
  この中で,
13
13
  ~~全てのグループに見合うレシピがあるやつだけ~~
14
14
  1つ以上のグループがレシピと合うやつだけ
15
- を出力すればよい.
15
+ を出力すればよい.
16
+
17
+ ---
18
+
19
+ [追記]
20
+ 実装してみたけど,「これはひどい」と言いたくなるコードになった…
21
+ (特に,材料のグループ分け全パターンを探すところがひどい有様)
22
+
23
+ ```C++
24
+ //EnumGroupingPtn()が使う作業関数
25
+ void EnumPtnWork(
26
+ const std::vector<unsigned int> &Mat,
27
+ std::vector< std::vector<unsigned int> > &Result,
28
+ int idx,
29
+ const std::vector< unsigned int > &Curr
30
+ )
31
+ {
32
+ if( idx == Mat.size() )
33
+ { Result.push_back( Curr ); return; }
34
+
35
+ for( int i=0; i<Curr.size(); ++i )
36
+ {
37
+ std::vector<unsigned int> C = Curr;
38
+ C[i] |= Mat[idx];
39
+ EnumPtnWork( Mat, Result, idx+1, C );
40
+ }
41
+
42
+ std::vector<unsigned int> C = Curr;
43
+ C.push_back( Mat[idx] );
44
+ EnumPtnWork( Mat, Result, idx+1, C );
45
+ }
46
+
47
+ //材料のグループ分けパターンを全パターン列挙した結果を作る
48
+ std::vector< std::vector<unsigned int> > EnumGroupingPtn( const std::vector<unsigned int> &Materials )
49
+ {
50
+ std::vector< std::vector<unsigned int> > Result;
51
+ EnumPtnWork( Materials, Result, 0, std::vector<unsigned int>() );
52
+ return Result;
53
+ }
54
+
55
+ //main
56
+ int main(void)
57
+ {
58
+ //材料の種類要定数:bitパターンで表す
59
+ const unsigned int Stone = 0x01;
60
+ const unsigned int Wood = 0x01 << 1;
61
+ const unsigned int Iron = 0x02 << 2;
62
+
63
+ //レシピ
64
+ // key = 作るのに必要な材料の組み合わせ
65
+ // value = <成果物の種類を表す定数(bitパターン), 成果物名称>
66
+ const std::map< unsigned int, std::pair<unsigned int, std::string> > Recipies
67
+ {
68
+ { Wood, { 0x1, "椅子" } },
69
+ { Wood|Iron|Stone, { 0x1<<1, "家" } },
70
+ { Iron, { 0x1<<2, "剣" } },
71
+ { Wood|Iron, { 0x1<<3, "ノコギリ" } }
72
+ };
73
+
74
+ //与えられた材料
75
+ const std::vector<unsigned int> Materials{ Stone, Wood, Iron };
76
+
77
+ //結果用データ
78
+ // vector of < 成果物の組み合わせを示す値, 表示用文字列 >
79
+ std::vector< std::pair<unsigned int,std::string> > Result;
80
+
81
+ {//メインの処理:材料のグループ分け全パターンについて調査する
82
+ for( const auto &MatGroups : EnumGroupingPtn( Materials ) )
83
+ {
84
+ //このグループ分けで作れる成果物群を調査
85
+ std::string Str_for_Disp; //※これは単なる結果表示用文字列
86
+ unsigned int CraftPtn = 0;
87
+ for( unsigned int MG : MatGroups )
88
+ {
89
+ auto iRecipie = Recipies.find( MG );
90
+ if( iRecipie != Recipies.end() )
91
+ {
92
+ if( CraftPtn>0 )Str_for_Disp += ", ";
93
+ Str_for_Disp += iRecipie->second.second;
94
+
95
+ CraftPtn |= iRecipie->second.first;
96
+ }
97
+ }
98
+ if( CraftPtn==0 )continue; //何も作れない場合
99
+
100
+ //何か作れる場合
101
+ bool Rejected = false;
102
+ for( auto i=Result.begin(); i!=Result.end(); /*NOP*/ )
103
+ {
104
+ unsigned int And = ( i->first & CraftPtn );
105
+
106
+ if( And == CraftPtn ) //既存よりも作れる物が少ない→このパターンを棄却
107
+ { Rejected=true; break; }
108
+ else if( And == i->first ) //既存よりもたくさん作れる→既存を棄却
109
+ { i = Result.erase( i ); }
110
+ else
111
+ { ++i; }
112
+ }
113
+
114
+ if( !Rejected ) //棄却されなかったならResultに追加
115
+ { Result.emplace_back( CraftPtn, Str_for_Disp ); }
116
+ }
117
+ }
118
+
119
+ //結果表示
120
+ for( const auto &r : Result )
121
+ { std::cout << r.second << std::endl; }
122
+
123
+ return 0;
124
+ }
125
+ ```

1

修正

2021/03/01 10:22

投稿

fana
fana

スコア12227

answer CHANGED
@@ -9,4 +9,7 @@
9
9
  * {B,C}, {A}
10
10
  * {A}, {B}, {C}
11
11
 
12
+ この中で,
12
- この中で,全てのグループに見合うレシピがあるやつだけを出力すればよい.
13
+ ~~全てのグループに見合うレシピがあるやつだけ~~
14
+ 1つ以上のグループがレシピと合うやつだけ
15
+ を出力すればよい.