题目描述:
就像题目名字一样,他们在玩一种类似于五子棋的游戏,只是规则和五子棋有一些不同。 就像五子棋一样,ITer和Kitty依次在棋盘上放置棋子,ITer放置黑子,Kitty放置白子。与五子棋不同的是,当一种颜色的X个棋子组成一行或一列或一个对角线的时候(X不一定等于5),执该颜色的子的玩家胜利。
如图,当X=5时,ITer胜利的三种方法:
下了一会儿后,ITer和Kitty觉得无聊了。于是,他们又加了一个类似围棋的规则:当一个连通分量(四连通)的棋子的四周被另一种棋子围住时,这些棋子就消失了,我们称这些子被“吃掉”了。
如图,三颗白棋的四周都被黑棋围住,所以这三颗棋子就应该消失。成为下图:
现在ITer和Kitty下了N步棋,ITer先手,每次下棋的位置用坐标表示。 现在ITer想知道,下了N步棋后,是否有人赢了,在第几步赢了,是否有不合法的走法。
输入:
输入文件第一行两个正整数N,X,表示下了N步棋,当一种颜色的X个棋子组成一行或一列或一个对角线的时候,执该颜色的子的玩家胜利。 接下来的N行,每行2个正整数Xi,Yi,当i为奇数时,表示ITer在第 i步下在了(Xi,Yi)上,当i为偶数时,表示Kitty在第 i步下在了(Xi,Yi)上。
输出:
如果ITer在前N步赢了,则输出“ITer X”(中间用空格连接),X表示ITer在第几步赢了。 如果Kitty在前N步赢了,则输出“Kitty X”(中间用空格连接),X表示Kitty在第几步赢了。 如果在N步以内有不合法的步,则输出“illegal”。
一步不合法有以下几种情况:
1. 这步下在了已经有棋子的格子上。
2. 在没有吃掉对方棋子的情况下,该步子所在的联通分量的棋子被对方的棋子吃掉。如图1,白子走在了红叉的位置上是不合法的,因为这样会使该联通分量被吃掉。
如图2,如果白子走在红叉的位置上是合法的,因为它吃掉了右边的两个黑子。走完这步后白子不会消失,棋盘上的子变成图3。
请忽视某一个人赢了以后出现的不合法的步。 如果既没有出现不合法的步,又没有决出胜负,则输出“draw”。 假设棋盘是无限的。
数据范围:
Subtask 1 30%:N≤20,X≤5,Xi,Yi≤10。 Subtask 2 70%:N≤1000,X≤10,1≤Xi,Yi≤1000 。
算法标签:模拟!!
恨模拟的根源是这道题!铭记了
思路:
只要你能想到的暴力都不会T,但我还是调了很久,最后绝望了....气啊....对于连成一条的暴力往两边扩张,看能不能达到个数。每次从当前点向外搜索,先判自己能否成为边界包死别人。再搜一次判断自己会不会被包死。
以下为调了半下午仍旧只有70+的我的代码(仅作纪念):
#include<bits/stdc++.h> #define il inline #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=1005;int n,st,a[N][N],op,fa[N],mx,my;bool pd,vis[N][N]; int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1}; il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;} il int getfa(int x){if(!fa[x])return x;return fa[x]=getfa(fa[x]);} il bool work(int x,int y,int col){ if(a[x][y]==3-col)return 1;if(a[x][y]==0)return 0; vis[x][y]=1; for(int i=0;i<4;i++){ int xx=dx[i]+x,yy=dy[i]+y; if(xx<0||yy<0||xx>mx||yy>my)return 0; if(!vis[xx][yy]&&work(xx,yy,col)==0)return 0; } return 1; } il void change(int x,int y){ if(!vis[x][y])return;vis[x][y]=0;a[x][y]=0; for(int i=0;i<4;i++){ int xx=dx[i]+x,yy=dy[i]+y; change(xx,yy); } } il void c(int x,int y){ if(!vis[x][y])return;vis[x][y]=0; for(int i=0;i<4;i++){ int xx=dx[i]+x,yy=dy[i]+y;c(xx,yy); } } int main() { freopen("123.out","w",stdout); n=read();st=read();op=1; for(int i=1;i<=n;i++){ int x=read(),y=read();if(pd)continue;mx=max(mx,x);my=max(my,y); if(op==1&&a[x][y]!=0){puts("illegal");pd=1;continue;} if(op==2&&a[x][y]!=0){puts("illegal");pd=1;continue; } a[x][y]=op; int k=x,res=1;while(k-1>0&&a[k-1][y]==op)res++,k--; k=x;while(k+1<=n&&a[k+1][y]==op)res++,k++; if(res>=st){ if(op==1)printf("ITer %d ",i); if(op==2)printf("Kitty %d ",i); pd=1;continue; } res=1;k=y;while(k-1>0&&a[x][k-1]==op)res++,k--; k=y;while(k+1<=n&&a[x][k+1]==op)res++,k++; if(res>=st){ if(op==1)printf("ITer %d ",i); if(op==2)printf("Kitty %d ",i); pd=1;continue; } int k1=x,k2=y;res=1; while(k1+1<=n&&k2+1<=n&&a[k1+1][k2+1]==op)res++,k1++,k2++; k1=x,k2=y;while(k1-1>0&&k2-1>0&&a[k1-1][k2-1]==op)res++,k1--,k2--; if(res>=st){ if(op==1)printf("ITer %d ",i); if(op==2)printf("Kitty %d ",i); pd=1;continue; } for(int i=0;i<4;i++)if(x+dx[i]<=mx&&x+dx[i]>0&&y+dy[i]<=my&&y+dy[i]>0){ int res=work(x+dx[i],y+dy[i],3-op);if(res==1)change(x+dx[i],y+dy[i]); else c(x+dx[i],y+dy[i]); } if(pdd(x,y))puts("illegal"); op=3-op; } if(!pd)puts("draw"); return 0; }
以下为在sgx神犇“援助”下的代码(没耐心本人):
#include<bits/stdc++.h> using namespace std; #define il inline #define _(d) while(d(isdigit(ch=getchar()))) const int N=1004;int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0}; int a[N][N],cnt,n,k,C,id[N][N],mx,my;bool vis[N]; il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;} il bool J(int r,int x,int y,int col,bool is,int fl){ vis[id[x][y]]=1; bool ff=0; for(int i=0;i<4;i++){ int tx=x+dx[i],ty=y+dy[i]; if((!a[tx][ty])||(is&&a[tx][ty]==3-col&&(!vis[id[tx][ty]]) &&(!J(r,tx,ty,3-col,0,0))))ff=1; } for(int i=0;i<4;i++){ int tx=x+dx[i],ty=y+dy[i]; if(a[tx][ty]==col){ if((!vis[id[tx][ty]])&&J(r,tx,ty,col,is,ff|fl)) ff=1; } } if(ff)return true; if(!is&&!(fl|ff)) a[x][y]=0; return false; } il bool work(int r,int x,int y,int t1,int t2){ int x1=0,x2=0; for(int i=0;i<=k;i++){ if(a[x+i*t1][y+i*t2]==C)x1++;else break; } for(int i=0;i<=k;i++){ if(a[x-i*t1][y-i*t2]==C)x2++;else break; } if(x1+x2-1>=k){ if(C==1)printf("ITer %d ",r); else printf("Kitty %d ",r); return 0; } return 1; } int main(){ n=read();k=read();C=2; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++)vis[j]=0; C=3-C; int x,y;x=read();y=read();id[x][y]=++cnt; if(a[x][y]){puts("illegal");return 0;} a[x][y]=C; memset(vis,0,sizeof(vis)); if(!J(i,x,y,C,1,0)){puts("illegal");return 0;} mx=max(mx,x);my=max(my,y); for(int j=-1;j<=1;j++)for(int l=-1;l<=1;l++){ if(!j&&!l)continue; if(!work(i,x,y,j,l)) return 0; } } puts("draw"); return 0; }
讨厌什么就要让它向你请安!立下爆刷模拟flag