SRM 534 250pt : EllysCheckers
問題概要
長さN(<20)のボードがあって各マスは空かチェッカーが置いてある。チェッカーは
- 右の空のマスにずらす。
- 1つ右、2つ右にチェッカーがあって3つ右が空のとき右に3つずらす。
のいずれかをする。最右にチェッカーが来たら即消す。交互に動かして、動かせなくなった方の負け。勝つのはどちらか求める問題。
解法
なんか賢い解き方あるらしいけどビットDPで間に合う。最右に来たチェッカーを消すというのに気づかずに色々時間をとられた。
acceptされたコード
計算量O(N*2^N)。
#include <string> using namespace std; int N; const int MAX_N = 20; bool visited[1<<MAX_N]; bool memo[1<<MAX_N]; struct EllysCheckers { string getWinner(string board) { N = board.length(); int bit = 0; for(int i=0; i<N-1; i++)if(board[i] == 'o'){ bit |= (1<<i); } return rec(bit) ? "YES" : "NO"; } bool rec(int bit){ if(visited[bit]){ return memo[bit]; } visited[bit] = true; bool& ret = memo[bit] = false; //STEP for(int i=0; i<N-1; i++)if(((bit>>i)&1) && !((bit>>(i+1))&1)){ int nbit = bit | (1<<(i+1)); nbit &= ~(1<<i); nbit &= ~(1<<(N-1)); ret |= !rec(nbit); } //JUMP for(int i=0; i<N-3; i++)if( ((bit>>i)&1) && ((bit>>(i+1))&1) && ((bit>>(i+2))&1) && !((bit>>(i+3))&1)){ int nbit = bit | (1<<(i+3)); nbit &= ~(1<<i); nbit &= ~(1<<(N-1)); ret |= !rec(nbit); } return ret; } };