SRM 315 Div1 Medium SillySudoku
問題概要
4x4のミニサイズの数独がある。
ある時点での盤面があたえられた時、この数独を完成パターンは何通りあるかを求めよ。
パズルで用いる数字は1-4であり、その他のルールは通常の数独と同じである。また数字がないマスは'-'で表される。
この回早解き勝負だったのかな。
解法
実行時間は気にしなくて良いよく、単純に再帰で数え上げればよい。
現在の盤面が合法かどうかをいちいち全て見て調べる(下コードではok関数)という効率の悪いやり方でも制限時間に間に合う。
ソースコード
map<vs,int> memo; int countWays(vector <string> board) { return rec(board); } int rec(vs b) { if(memo.count(b))return memo[b]; if(!ok(b))return memo[b]=0; bool f=0; int ret=0; rep(i,4)rep(j,4)if(b[i][j]=='-') { f=1; rep(n,4) { b[i][j]='1'+n; ret+=rec(b); b[i][j]='-'; } goto END; } END:return f?(memo[b]=ret):1; } bool ok(vs b) { //col rep(j,4) { bool u[4]={0}; rep(i,4) { if(b[i][j]=='-')continue; if(u[b[i][j]-'1'])return 0; u[b[i][j]-'1']=1; } } //row rep(i,4) { bool u[4]={0}; rep(j,4) { if(b[i][j]=='-')continue; if(u[b[i][j]-'1'])return 0; u[b[i][j]-'1']=1; } } //box rep(y,2)rep(x,2) { bool u[4]={0}; rep(i,2)rep(j,2) { if(b[y*2+i][x*2+j]=='-')continue; if(u[b[y*2+i][x*2+j]-'1'])return 0; u[b[y*2+i][x*2+j]-'1']=1; } } return 1; }
メモ化は別に要らなかったみたい……
System Test
Passed.
でも解くの遅い。。。orz