题目链接:
题意:给出一个4*4的棋盘,x和o两人轮流放。先放够连续四个的赢。给定一个局面,下一个轮到x放。问x是否有必胜策略?若有,输出能够赢的最小的坐标?
思路:(1)Maxfind(Min):每次放x,若得到的Max大于等于Min,则直接返回Max。因为Minfind要用这个Max更新Min,若x放置之后能够得到一个比Min大的,显然这样放最好;因为Min无法用Max更新;
(2)Minfind(Max)类似;
(3)因此,枚举第一个人放的位置,Minfind,返回的是INF则胜利。
char s[10][10];int ansX,ansY,chessCnt;int isOver(int x,int y){ int r[4]={0},c[4]={0},i,j; clr(r,0); clr(c,0); FOR0(i,4) FOR0(j,4) { if(s[i][j]=='x') r[i]++,c[j]++; if(s[i][j]=='o') r[i]--,c[j]--; } if(abs(r[x])==4||abs(c[y])==4) return 1; int cnt1=0,cnt2=0; FOR0(i,4) { if(s[i][i]=='x') cnt1++; if(s[i][3-i]=='x') cnt2++; if(s[i][i]=='o') cnt1--; if(s[i][3-i]=='o') cnt2--; } if(abs(cnt1)==4&&x==y||abs(cnt2)==4&&x+y==3) return 1; return 0;}int Minfind(int,int,int);int Maxfind(int x,int y,int Min){ int temp,Max=-INF,i,j; if(isOver(x,y)) return Max; if(chessCnt==16) return 0; FOR0(i,4) FOR0(j,4) if(s[i][j]=='.') { s[i][j]='x'; chessCnt++; temp=Minfind(i,j,Max); chessCnt--; s[i][j]='.'; if(temp>Max) Max=temp; if(Max>=Min) return Max; } return Max;}int Minfind(int x,int y,int Max){ int temp,Min=INF,i,j; if(isOver(x,y)) return Min; if(chessCnt==16) return 0; FOR0(i,4) FOR0(j,4) if(s[i][j]=='.') { s[i][j]='o'; chessCnt++; temp=Maxfind(i,j,Min); chessCnt--; s[i][j]='.'; if(temp<Min) Min=temp; if(Min<=Max) return Min; } return Min;}int check(){ int Max=-INF,i,j,temp; FOR0(i,4) FOR0(j,4) if(s[i][j]=='.') { s[i][j]='x'; chessCnt++; temp=Minfind(i,j,Max); chessCnt--; s[i][j]='.'; if(temp>Max) Max=temp,ansX=i,ansY=j; if(Max==INF) return 1; } return 0;}int main(){ char op[5]; while(scanf("%s",op)&&op[0]!='$') { int i,j; chessCnt=0; FOR0(i,4) { RD(s[i]); FOR0(j,4) chessCnt+=s[i][j]!='.'; } if(chessCnt<=4||!check()) puts("#####"); else printf("(%d,%d)\n",ansX,ansY); }}