Quiz
https://atcoder.jp/contests/abc025/tasks/abc025_c
Submit
https://atcoder.jp/contests/abc025/submissions/4408334
Note
- 片方がスコアを最大にしようと動き、もう片方がスコアを最小にしようと動くとき、ミニマックス法で先読みする
- Wikipedia参照
書き方
- 1つの書き方ではあるが、私はdfsで書いた
- 最初は盤面が全て未決定の状態
* * * * * * * * *
- そこから1つ○をつけて次のdfsに渡す
* * * * * o * * *
- この全てのシミュレーションをどう書くかは、以下のようにした
- 盤面を1コマ書き換える
- 1ステップ進んだ状態で再度dfsを呼ぶ
- dfsから戻ってきたら盤面を戻す
- 対応するコードは以下
// chokudai's turn if(step%2==1){ ll max_score = -inf; FOR(i, 0, 3){ FOR(j, 0, 3){ if(G[i][j]=='*'){ G[i][j] = 'o'; ll score = dfs(step+1); max_score = max(max_score, score); G[i][j] = '*'; } } } ret = max_score; }
- dfsではお決まりだが、最終盤面を終端として止まるようにしておく
最後にスコア分解
- ここはちょっと見苦しい
- score = 直大スコア - 直子スコア
- として進めてきたが、提出すべきは双方のスコア
- 各コードをpair版にしてもいいが、最終盤面のパターンは雑に作っても29なので、全て作ってscoreと比較
- 一致すればその盤面で双方のスコアを求めて提出、とした
学び
- ミニマックス法を使った全探索
感想
- C問題にしては難しい?
- 慣れている人(writer)はdfsを書くのにも慣れているので、簡単に思えるのかもしれない
Code
#include<algorithm> #include<complex> #include<ctype.h> #include<iomanip> #include<iostream> #include<map> #include<math.h> #include<numeric> #include<queue> #include<set> #include<stack> #include<stdio.h> #include<string> #include<string> #include<vector> using namespace std; typedef long long ll; #define FOR(i,a,b) for(ll i=(a);i<(b);++i) #define ALL(v) (v).begin(), (v).end() #define p(s) cout<<(s)<<endl #define p2(s, t) cout << (s) << " " << (t) << endl #define br() p("") #define pn(s) cout << (#s) << " " << (s) << endl #define p_yes() p("YES") #define p_no() p("NO") const ll mod = 1e9 + 7; const ll inf = 1e18; ll B[2][3]; ll C[3][2]; char G[3][3]; pair<ll, ll> final_pair(){ // point ll man = 0; ll woman = 0; FOR(i, 0, 3){ FOR(j, 0, 3){ char c = G[i][j]; if(c!='o' && c!='x'){ return {-1, -1}; } } } // B FOR(i, 0, 2){ FOR(j, 0, 3){ if(G[i][j]==G[i+1][j]){ man += B[i][j]; }else{ woman += B[i][j]; } } } // C FOR(i, 0, 3){ FOR(j, 0, 2){ if(G[i][j]==G[i][j+1]){ man += C[i][j]; }else{ woman += C[i][j]; } } } return {man, woman}; } ll final_score(){ auto p = final_pair(); return p.first - p.second; } ll dfs(ll step){ if(step==10){ return final_score(); } ll ret; // chokudai's turn if(step%2==1){ ll max_score = -inf; FOR(i, 0, 3){ FOR(j, 0, 3){ if(G[i][j]=='*'){ G[i][j] = 'o'; ll score = dfs(step+1); max_score = max(max_score, score); G[i][j] = '*'; } } } ret = max_score; } // naoko's turn else{ ll min_score = inf; FOR(i, 0, 3){ FOR(j, 0, 3){ if(G[i][j]=='*'){ G[i][j] = 'x'; ll score = dfs(step+1); min_score = min(min_score, score); G[i][j] = '*'; } } } ret = min_score; } return ret; } // final scoreを与えたときのchokudai's score, naoko's scoreを返す pair<ll, ll> devide(ll score){ // 盤面総当たり FOR(f, 0, 1<<9){ ll man = 0; ll woman = 0; FOR(keta, 0, 9){ ll i = keta / 3; ll j = keta % 3; if(f >> keta & 1){ G[i][j] = 'o'; man++; }else{ G[i][j] = 'x'; woman++; } } if(man==5 && woman==4){ if(score == final_score()){ return final_pair(); } } } return {-1L, -1L}; } int main(){ cin.tie(0); ios::sync_with_stdio(false); // input FOR(i, 0, 2){ FOR(j, 0, 3){ cin >> B[i][j]; } } FOR(i, 0, 3){ FOR(j, 0, 2){ cin >> C[i][j]; } } FOR(i, 0, 3){ FOR(j, 0, 3){ G[i][j] = '*'; } } ll score = dfs(1); auto p = devide(score); p(p.first); p(p.second); return 0; }