题目大意
黑棋从x轴0连到N算胜利,白棋从y轴0连到N算胜利
让你判断黑棋最后一步是否胜利
具体见原网页
分析
对于线采用两种存放方式:
一种用四维数组实现,便于询问两点间是否有线
另一种用结构体实现,方便对线的集合进行操作
最后用BFS判断各个线的联通分量是否有跨越两边边界的
连线的时候是不能与其他线之间有交集的,这道题的关键就是如何判断一条线连下去是否会产生交集。
这道题我按着一开始的思路写了后发现问题越来越多,感觉就在不断打补丁,纠结了几个小时后还是换了看似最暴力的方法但思路要清晰了许多。
说一下一开始复杂的而且还没改对的思路:
一开始认为只要一条线连上了这条线所占的两个格子就都不能再放了,所以就用用了一个数组标记上,后面出现WA测数据才发现还有下图左边的情况,然后就单独处理了这种情况,之后有发现还有下图右边的情况,感觉就是在不断打补丁,最后该完了觉得没问题了数据也过不了,不知道哪里的问题实在没办法还是放弃了。。。
后面还是按照枚举的方法来判断可能出现交集的边
总结
以后做模拟题一定要仔细想好思路了再开始写。
还有就是如果写了一段时间发现方法很繁琐一定要敢于放弃这个方法,补不过来的方法及时换。
这几天模拟题真是写伤了,还好这个是最后道了。
代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
using namespace std;
int N,M;
int cover[30][30];//cover[x][y]表示(x,y),值为0表示没有被边覆盖,1表示黑边覆盖,2表示白边覆盖
int line[30][30][30][30];//判断(xa,ya)到(xb,yb) 1黑边 2b白边
int node[30][30];//node[x][y]为1表示黑点,2表示白点
int nodebj[30][30];
int bj[30][30][30][30];//Check时搜过的边标记上
int xx[8]={-2,-1,1,2,2,1,-1,-2};
int yy[8]={1,2,2,1,-1,-2,-2,-1};
struct LINE
{
int xa;int ya;
int xb;int yb;
}line1[2005];
int cnt_line1;
bool Is_out(int x,int y)
{
if(x>=0 && x<=N && y>=0 && y<=N)return 0;
else return 1;
}
bool Is_line(int xx1,int yy1,int xx2,int yy2)
{
if(xx1<0 || xx1 >N || yy1<0 || yy1>N || xx2 <0 || xx2>N || yy2<0 || yy2>N)return 0;
if(line[xx1][yy1][xx2][yy2]==0)return 0;
return 1;
}
void Add_node(int x,int y,int color)
{
node[x][y]=color;
int flag;
for(int i=0;i<8;i++)//8个方向寻找能连上线的点
{
int tx=x+xx[i];
int ty=y+yy[i];
if(Is_out(tx,ty))continue;
int flag=0;//0表示能放
int xx1,yy1,xx2,yy2;
if(node[tx][ty]==color )
{
if(abs(tx-x)==1 && (tx-x)*(ty-y)<0)
{
xx1=min(tx,x);yy1=max(ty,y);
xx2=max(tx,x);yy2=min(ty,y);
if(Is_line(xx1-1,yy1,xx2,yy2+1)){flag=1;}
if(Is_line(xx1,yy1-1,xx2+1,yy2)){flag=1;}
if(Is_line(xx1-1,yy1-1,xx2,yy2+2)){flag=1;}
if(Is_line(xx1,yy1-1,xx2+1,yy2+2)){flag=1;}
if(Is_line(xx1-1,yy1-2,xx2,yy2+1)){flag=1;}
if(Is_line(xx1,yy1-2,xx2+1,yy2+1)){flag=1;}
if(Is_line(xx1,yy1-1,xx2,yy2+3)){flag=1;}
if(Is_line(xx1,yy1-2,xx2,yy2+2)){flag=1;}
if(Is_line(xx1,yy1-3,xx2,yy2+1)){flag=1;}
}
else if(abs(tx-x)==1 && (tx-x)*(ty-y)>0)
{
xx1=min(tx,x);yy1=min(ty,y);
xx2=max(tx,x);yy2=max(ty,y);
if(Is_line(xx1-1,yy1,xx2,yy2-1)){flag=1;}
if(Is_line(xx1,yy1+1,xx2+1,yy2)){flag=1;}
if(Is_line(xx1,yy1+1,xx2,yy2-3)){flag=1;}
if(Is_line(xx1,yy1+2,xx2,yy2-2)){flag=1;}
if(Is_line(xx1,yy1+3,xx2,yy2-1)){flag=1;}
if(Is_line(xx1-1,yy1+1,xx2,yy2-2)){flag=1;}
if(Is_line(xx1,yy1+1,xx2+1,yy2-2)){flag=1;}
if(Is_line(xx1-1,yy1+2,xx2,yy2-1)){flag=1;}
if(Is_line(xx1,yy1+2,xx2+1,yy2-1)){flag=1;}
}
else if(abs(tx-x)==2 && (tx-x)*(ty-y)<0)
{
xx1=min(tx,x);yy1=max(ty,y);
xx2=max(tx,x);yy2=min(ty,y);
if(Is_line(xx1,yy1+1,xx2-1,yy2)){flag=1;}
if(Is_line(xx1+1,yy1,xx2,yy2-1)){flag=1;}
if(Is_line(xx1-1,yy1-1,xx2-1,yy2+1)){flag=1;}
if(Is_line(xx1,yy1-1,xx2,yy2+1)){flag=1;}
if(Is_line(xx1+1,yy1-1,xx2+1,yy2+1)){flag=1;}
if(Is_line(xx1,yy1-1,xx2-1,yy2+2)){flag=1;}
if(Is_line(xx1,yy1-2,xx2-1,yy2+1)){flag=1;}
if(Is_line(xx1+1,yy1-1,xx2,yy2+2)){flag=1;}
if(Is_line(xx1+1,yy1-2,xx2,yy2+1)){flag=1;}
}
else if(abs(tx-x)==2 && (tx-x)*(ty-y)>0)
{
//if(x==4 && y==3 && tx==2 && ty==2)cout<<"a"<<endl;
xx1=min(tx,x);yy1=min(ty,y);
xx2=max(tx,x);yy2=max(ty,y);
if(Is_line(xx1,yy1-1,xx2-1,yy2)){flag=1;}
if(Is_line(xx1+1,yy1,xx2,yy2+1)){flag=1;}
if(Is_line(xx1-1,yy1+1,xx2-1,yy2-1)){flag=1;}
if(Is_line(xx1,yy1+1,xx2,yy2-1)){flag=1;}
if(Is_line(xx1+1,yy1+1,xx2+1,yy2-1)){flag=1;}
if(Is_line(xx1,yy1+1,xx2-1,yy2-2)){flag=1;}
if(Is_line(xx1,yy1+2,xx2-1,yy2-1)){flag=1;}
if(Is_line(xx1+1,yy1+1,xx2,yy2-2)){flag=1;}
if(Is_line(xx1+1,yy1+2,xx2,yy2-1)){flag=1;}
}
if(flag==1)continue;
//(x,y)(tx,ty)能放
line[x][y][tx][ty]=color;
line[tx][ty][x][y]=color;
// if(color==1)cout<<"("<<x<<","<<y<<") ("<<tx<<","<<ty<<")"<<endl;
if(color==1)//如果是黑边就保存下来
{
//cout<<max(tx,x)<<" "<<max(ty,y)<<" "<<min(tx,x)+1<<" "<<min(ty,y)+1<<endl;
line1[++cnt_line1].xa=x;
line1[cnt_line1].ya=y;
line1[cnt_line1].xb=tx;
line1[cnt_line1].yb=ty;
}
}
}
}
void Travel()
{
for(int y=N;y>=0;y--)
{
for(int x=0;x<=N;x++)
{
cout<<cover[x][y];
}
cout<<endl;
}
for(int i=1;i<=cnt_line1;i++)
{
cout<<"("<<line1[i].xa<<","<<line1[i].ya<<") ("<<line1[i].xb<<","<<line1[i].yb<<")"<<endl;
}
}
void Bfs(int x,int y,int &end0,int &endN)
{
memset(nodebj,0,sizeof(nodebj));
queue<int> Qx;
queue<int> Qy;
Qx.push(x);
Qy.push(y);
nodebj[x][y]=1;
while(!Qx.empty())
{
x=Qx.front();Qx.pop();
y=Qy.front();Qy.pop();
for(int i=0;i<8;i++)
{
int tx=x+xx[i];
int ty=y+yy[i];
if(Is_out(tx,ty))continue;//判断是否出界
if(nodebj[tx][ty]==0 && line[x][y][tx][ty]==1)
{
nodebj[tx][ty]=1;
if(tx==0)end0=1;
if(tx==N)endN=1;
Qx.push(tx);
Qy.push(ty);
}
}
}
}
bool Check()
{
int xa,ya,xb,yb;
int end0,endN;
for(int i=1;i<=cnt_line1;i++)//从每条边开始进行BFS
{
xa=line1[i].xa;
ya=line1[i].ya;
end0=0;endN=0;
if(nodebj[xa][ya]==1)continue;
if(xa==0)end0=1;
if(xa==N)endN=1;
Bfs(xa,ya,end0,endN);
if(end0==1 && endN==1)return 1;
}
return 0;
}
void Init()
{
memset(cover,0,sizeof(cover));
memset(node,0,sizeof(node));
memset(line,0,sizeof(line));
memset(bj,0,sizeof(bj));
cnt_line1=0;
}
int main()
{
int x,y;
while(scanf("%d%d",&N,&M)!=EOF)
{
Init();
if(N==0 && M==0)break;
for(int i=1;i<=M;i++)
{
scanf("%d%d",&x,&y);
if(i%2==1)Add_node(x,y,1);
else Add_node(x,y,2);
}
//Travel();
if(Check()==1)cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
return 0;
}