Codeforces 71 D. Solitaire
問題
トランプ54枚のうちnm枚がn行m列に並んでいる。
ジョーカーを余っているカードの好きなものと取り替えてよい。
このとき、次のうちいずれかの条件を満たす3x3の正方形を重ならないように二つ取ることが出来るか判定せよ。
- 全てのスートが同じ
- 全ての数字が互いに異なる
制約条件
n,m≦17
nm≦52
方針
全探索。
ソースコード
これは酷い。
int h,w; int cd[20][20]; bool use[200]; int parse(string s){ int res=0; if(isdigit(s[1]))return -(s[1]-'0'); switch(s[0]){ case 'A': res=1; break; case 'T': res=10; break; case 'J': res=11; break; case 'Q': res=12; break; case 'K': res=13; break; default: res=s[0]-'0'; } res*=5; switch(s[1]){ case 'S':; break; case 'H': res+=1; break; case 'D': res+=2; break; case 'C': res+=3; break; } return res; } const char *name="SHDC"; const char *ranks="-A23456789TJQK"; string ans1,ans2; bool ok(int y,int x){ bool samesuit=1; bool use[14]={}; rep(i,3)rep(j,3){ if(cd[i+y][j+x]%5!=cd[y][x]%5)samesuit=0; use[cd[i+y][j+x]/5]=1; } int cnt=0; rep(i,14)if(use[i])cnt++; return samesuit||cnt==9; } bool ck(){ rep(i,h-2)rep(j,w-2){ if(!ok(i,j))continue; rep(k,h-2)rep(l,w-2)if(abs(i-k)>=3||abs(j-l)>=3){ if(!ok(k,l))continue; stringstream ss; ss<<"Put the first square to ("<<i+1<<", "<<j+1<<")."; ans1=ss.str(); stringstream tt; tt<<"Put the second square to ("<<k+1<<", "<<l+1<<")."; ans2=tt.str(); return 1; } } return 0; } void run() { cin>>h>>w; int j1y=-1,j1x=-1,j2y=-1,j2x=-1; rep(i,h)rep(j,w){ string s; cin>>s; cd[i][j]=parse(s); if(cd[i][j]==-1)j1y=i, j1x=j; else if(cd[i][j]==-2)j2y=i, j2x=j; use[cd[i][j]]=1; } if(j1y<0&&j2y<0){ if(ck()){ cout<<"Solution exists."<<endl; cout<<"There are no jokers."<<endl; cout<<ans1<<endl<<ans2<<endl; return; } cout<<"No solution."<<endl; return; } if(j1y>=0&&j2y<0){ rep(suit1,4)for(int rank1=1;rank1<=13;rank1++){ if(!use[suit1+rank1*5]){ cd[j1y][j1x]=suit1+rank1*5; if(ck()){ cout<<"Solution exists."<<endl; cout<<"Replace J1 with "<<ranks[rank1]<<name[suit1]<<"."<<endl; cout<<ans1<<endl<<ans2<<endl; return; } } } cout<<"No solution."<<endl; return; } if(j1y<0&&j2y>=0){ rep(suit1,4)for(int rank1=1;rank1<=13;rank1++){ if(!use[suit1+rank1*5]){ cd[j2y][j2x]=suit1+rank1*5; if(ck()){ cout<<"Solution exists."<<endl; cout<<"Replace J2 with "<<ranks[rank1]<<name[suit1]<<"."<<endl; cout<<ans1<<endl<<ans2<<endl; return; } } } cout<<"No solution."<<endl; return; } rep(suit1,4)for(int rank1=1;rank1<=13;rank1++)if(!use[suit1+rank1*5]){ rep(suit2,4)for(int rank2=1;rank2<=13;rank2++) if((suit1!=suit2||rank1!=rank2)&&!use[suit2+rank2*5]){ cd[j1y][j1x]=suit1+rank1*5; cd[j2y][j2x]=suit2+rank2*5; if(ck()){ cout<<"Solution exists."<<endl; cout<<"Replace J1 with "<<ranks[rank1]<<name[suit1]; cout<<" and J2 with "<<ranks[rank2]<<name[suit2]<<"."<<endl; cout<<ans1<<endl<<ans2<<endl; return; } } } cout<<"No solution."<<endl; }