Connect
Description
Your task is to decide if a specified sequence of moves in the board game Twixt ends with a winning move. In this version of the game, different board sizes may be specified. Pegs are placed on a board at integer coordinates in the range [0, N]. Players Black and White use pegs of their own color. Black always starts and then alternates with White, placing a peg at one unoccupied position (x,y). Black's endzones are where x equals 0 or N, and White's endzones are where y equals 0 or N. Neither player may place a peg in the other player's endzones. After each play the latest position is connected by a segment to every position with a peg of the same color that is a chess knight's move away (2 away in one coordinate and 1 away in the other), provided that a new segment will touch no segment already added, except at an endpoint. Play stops after a winning move, which is when a player's segments complete a connected path between the player's endzones. For example Figure 1 shows a board with N=4 after the moves (0,2), (2,4), and (4,2). Figure 2 adds the next move (3,2). Figure 3a shows a poor next move of Black to (2,3). Figure 3b shows an alternate move for Black to (2,1) which would win the game. Figure 4 shows the board with N=7 after Black wins in 11 moves: (0, 3), (6, 5), (3, 2), (5, 7), (7, 2), (4, 4), (5, 3), (5, 2), (4, 5), (4, 0), (2, 4). Input
The input contains from 1 to 20 datasets followed by a line containing only two zeroes, "0 0". The first line of each dataset contains the maximum coordinate N and the number of total moves M where 3 < N < 21, 4 < M < 250, and M is odd. The rest of the dataset contains a total of M coordinate pairs, with one or more pairs per line. All numbers on a line will be separated by a space. M being odd means that Black will always be the last player. All data will be legal. There will never be a winning move before the last move.
Output
The output contains one line for each data set: "yes" if the last move is a winning move and "no" otherwise.
Sample Input 4 5 0 2 2 4 4 2 3 2 2 3 4 5 0 2 2 4 4 2 3 2 2 1 7 11 0 3 6 5 3 2 5 7 7 2 4 4 5 3 5 2 4 5 4 0 2 4 0 0 Sample Output no yes yes Source |
提示
题意:
给出n*n的矩阵(3<n<21),之后再给出m个点(4<m<250),黑子先手,白子后手,它们按照坐标顺序依次放入棋盘(矩阵)中,并且它们会以象棋中马的走法进行相互连线,如果之前的连线阻断了当前连线,那么这条线将不存在。那么黑子能否在最后一步时完成从最左端到达最右端。
思路:
输入输出都没什么问题,主要是线段判交,这条线段干脆就和其他线段直接用计算几何的线段判交就行了,只是不包括端点。
示例程序
Source Code
Problem: 2706 Code Length: 3132B
Memory: 604K Time: 16MS
Language: GCC Result: Accepted
#include <stdio.h>
#include <string.h>
struct point
{
int x,y;
}p[250];
struct
{
int color,id;
}map[21][21]; //棋盘各个棋子的编号以及颜色
int n,m,w[250][250],walk[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}}; //w数组记录连线情况
int cross(struct point a,struct point b,struct point o)
{
return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);
}
int judge(struct point a,struct point b,struct point c,struct point d)
{
return cross(a,c,b)*cross(a,b,d)>0&&cross(c,a,d)*cross(c,d,b)>0;
}
int bfs()
{
int v[250],q[125],i,i1,f,top;
for(i=0;n>=i;i++) //枚举最左边的点
{
if(map[0][i].color!=1)
{
continue;
}
memset(v,0,sizeof(v));
f=0;
top=0;
q[top]=map[0][i].id;
top++;
v[q[f]]=1;
while(f<top)
{
if(p[q[f]].x==n)
{
return 1;
}
for(i1=0;m>i1;i1++)
{
if(v[i1]==0&&w[q[f]][i1]==1)
{
q[top]=i1;
top++;
v[i1]=1;
}
}
f++;
}
}
return 0;
}
void f(int x,int y,int color)
{
int i,i1,i2,x1,y1,pos,pos1;
struct point a,b;
pos=map[x][y].id;
for(i=0;8>i;i++)
{
x1=x+walk[i][0];
y1=y+walk[i][1];
if(x1>=0&&y1>=0&&x1<=n&&y1<=n&&map[x1][y1].color==color) //颜色是否一样且不超边界
{
pos1=map[x1][y1].id;
a.x=x;
a.y=y;
b.x=x1;
b.y=y1;
for(i1=0;m>i1;i1++)
{
for(i2=i1+1;m>i2;i2++)
{
if(w[i1][i2]==0) //未连线
{
continue;
}
if(judge(a,b,p[i1],p[i2])==1) //判断是否相交
{
break;
}
}
if(i2!=m)
{
break;
}
}
if(i1==m) //没有线段阻挡,连线
{
w[pos][pos1]=1;
w[pos1][pos]=1;
}
}
}
}
int main()
{
int i,flag;
scanf("%d %d",&n,&m);
while(n!=0||m!=0)
{
flag=0;
memset(map,-1,sizeof(map));
memset(w,0,sizeof(w));
for(i=0;m>i;i++)
{
scanf("%d %d",&p[i].x,&p[i].y);
if(flag==-1) //不是最后一步就达成目标,后面的数据不做处理
{
continue;
};
map[p[i].x][p[i].y].id=i;
if(i%2==0) //黑子
{
map[p[i].x][p[i].y].color=1;
f(p[i].x,p[i].y,1); //黑子连线
}
else //白子
{
map[p[i].x][p[i].y].color=2;
f(p[i].x,p[i].y,2); //白子连线
}
if(bfs()==1) //当前状态是否能达成目标
{
if(i!=m-1) //不是最后一步的情况
{
flag--;
}
else //最后一步的情况
{
flag++;
}
}
}
if(flag==1)
{
printf("yes\n");
}
else
{
printf("no\n");
}
scanf("%d %d",&n,&m);
}
return 0;
}