题意:给你一个N+1*N+1的棋盘(从0到N),给定了这局棋的下棋过程,黑子先下,且总的下棋步数为奇数,也就保证最后一个下的是黑棋。其中,每下一步棋如果它的周围(中国象棋或是国际象棋中一个日字的走法)8个点存在同色的棋,并且两个棋之间没有其他棋子连线所拦,那么就将这连个棋子连线。如果黑棋从左边界到右边界有一条线贯穿或白棋从上边界到下边界有一条线贯穿,贯穿的那方就获得胜利。原题意为问黑子的最后一步是否能使得这局棋分出胜负。实际上题意有所差错,在所有棋子下完之后只需要判断是否存在赢家即可(无论黑白)当存在赢家输出yes,黑白均没胜利输出no。
思路:首先必不可少的是判线段是否相交,其次,就是怎么去模拟了。本人用的是完全无脑模拟,就是黑棋一步白棋一步,单独记录黑棋和白棋的每个坐标每当下棋之后就与其他坐标想比对,看看是否在存在8点之一,若存在那么先连线(但不存储)将连线与所有黑白连线比较,看看是否存在相交,当不存在的时候就把黑线存入黑线的存储结构里,白棋同理。最后一遍循环跑完,检查是否有左右或上下贯通。检查联通可使用并查集,将坐标化为一个独立的数值即可。
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define eps 1e-8
#define zero(x) (((x) > 0 ? (x) : (x)) < eps)
using namespace std;
struct Point { double x,y; };
struct Line { Point a,b; };
struct P
{
int x,y;
};
int arr1[700],arr2[700];
double xmult(Point p1, Point p2, Point p)
{
return (p1.x - p.x)*(p2.y - p.y)-(p2.x-p.x)*(p1.y-p.y);
}
bool isIntersected(Line u,Line v)
{
return (max(u.a.x,u.b.x)>=min(v.a.x,v.b.x)) &&
(max(v.a.x,v.b.x)>=min(u.a.x,u.b.x)) &&
(max(u.a.y,u.b.y)>=min(v.a.y,v.b.y)) &&
(max(v.a.y,v.b.y)>=min(u.a.y,u.b.y)) &&
(xmult(u.a,v.a,u.b)*xmult(u.a,u.b,v.b) > eps)&&
(xmult(v.a,u.a,v.b)*xmult(v.a,v.b,u.b) > eps);
}
void init()
{
for(int i=0;i<=700;i++)
{
arr1[i]=arr2[i]=i;
}
}
int Find1(int r)
{
return r==arr1[r]?r:arr1[r]=Find1(arr1[r]);
}
int Find2(int r)
{
return r==arr2[r]?r:arr2[r]=Find2(arr2[r]);
}
void Union1(int x,int y)
{
int fx=Find1(x);
int fy=Find1(y);
if(fx!=fy)
{
arr1[fx]=fy;
}
}
void Union2(int x,int y)
{
int fx=Find2(x);
int fy=Find2(y);
if(fx!=fy)
{
arr2[fx]=fy;
}
}
int main()
{
int n,m;
int x,y;
int k;
while(scanf("%d%d",&n,&m),n||m)
{
init();
int flag;
int t1=0,t2=0;
int l1=0,l2=0;
P p_black[200],p_white[200];
Line black[200],white[200],line;
for(int i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
if(i%2==0){
for(int j=0;j<t1;j++)
{
flag=0;
if((abs(p_black[j].x-x)==2&&abs(p_black[j].y-y)==1)||
(abs(p_black[j].x-x)==1&&abs(p_black[j].y-y)==2))
{
line.a.x=x;
line.a.y=y;
line.b.x=p_black[j].x;
line.b.y=p_black[j].y;
for(k=0;k<l2;k++)
{
if(isIntersected(line,white[k])) {flag=1; break;}
}
for(k=0;k<l1;k++)
{
if(isIntersected(line,black[k])) {flag=1; break;}
}
if(!flag)
{
black[l1].a.x=line.a.x;
black[l1].a.y=line.a.y;
black[l1].b.x=line.b.x;
black[l1].b.y=line.b.y;
l1++;
Union1(x*30+y,p_black[j].x*30+p_black[j].y);
}
}
}
p_black[t1].x=x;
p_black[t1++].y=y;
}
else
{
for(int j=0;j<t2;j++)
{
flag=0;
if((abs(p_white[j].x-x)==2&&abs(p_white[j].y-y)==1)||
(abs(p_white[j].x-x)==1&&abs(p_white[j].y-y)==2))
{
line.a.x=x;
line.a.y=y;
line.b.x=p_white[j].x;
line.b.y=p_white[j].y;
for(k=0;k<l2;k++)
{
if(isIntersected(line,white[k])) {flag=1; break;}
}
for(k=0;k<l1;k++)
{
if(isIntersected(line,black[k])) {flag=1; break;}
}
if(!flag)
{
white[l2].a.x=line.a.x;
white[l2].a.y=line.a.y;
white[l2].b.x=line.b.x;
white[l2].b.y=line.b.y;
l2++;
Union2(x*30+y,p_white[j].x*30+p_white[j].y);
}
}
}
p_white[t2].x=x;
p_white[t2++].y=y;
}
}
flag=0;
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
{
if(Find1(i)==Find1(n*30+j)||Find2(i)==Find2(n*30+j)){
printf("yes\n");
flag=1;
break;
}
}
if(flag) break;
}
if(!flag) printf("no\n");
}
return 0;
}