Connect
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1359 | Accepted: 452 |
Description
![]() | ![]() | ![]() | ![]() | ![]() |
Figure 1 | Figure 2 | Figure 3a | Figure 3b | Figure 4 |
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優YoU http://user.qzone.qq.com/289065406/blog/1308890557
思路:
美(sang)妙(xin)至(bing)极(kuang)的模拟,但是难度不大,难点主要在于判断连线是否相交。
这个题一定要画好了,细心才能做出来(太恶心了)
如上图放下一只棋子后,先检查其附近的8个方位是否存在同色棋子,若存在,则检查是否允许与该同色棋子连线。
检查连线方法如下图,以30度的方位为例:
如上图,当放下新棋子后,若检测到30度方位存在与其同色的棋子,则在连接蓝线之前,先检查是否已存在9条红色的线,当且仅当这9条红线都不存在时,才允许连接蓝线。
其他7个方位也是同样做法。
连接起来线就好说了,直接bfs看一看能不能走到最后边界就可以了。
小优的用了两次bfs,不过我也觉得数据给的应该是合法的,毕竟如果赢了那还下什么。
另外就是连线的时候,判断九条线的时候可以稍微暴力一下白色的点们的连线,如果能连线且相交自然是不能连接的,判断相交自然是用叉积。
不过这种思想是最简单的,只要画好图就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN=250+5;
int n,m;
int lastx,lasty;
int tu[30][30];//用来给点编号
bool link[MAXN][MAXN];//表示两个点之间是否连线
//8个方位
int xx[8]= {-1,-2,-2,-1, 1, 2,2,1};
int xy[8]= { 2, 1,-1,-2,-2,-1,1,2};
struct node
{
int color;
int x,y;
int connet[8];
int cnt;
} peg[MAXN];
void linepeg(int i);//把此点和其余的点连线
bool checkwin();
int main()
{
int i;
while(~scanf("%d%d",&n,&m))
{
if(!n&&!m)break;
memset(tu,0,sizeof(tu));
memset(link,0,sizeof(link));
for(i=1; i<=m; ++i)
{
int x,y;
scanf("%d%d",&x,&y);
tu[x][y]=i;
peg[i].color=i%2;
peg[i].x=x;
peg[i].y=y;
peg[i].cnt=0;
if(i==m)
{
lastx=x;
lasty=y;
}
linepeg(i);//连线
}
if(checkwin())puts("yes");//搜索
else puts("no");
}
return 0;
}
void linepeg(int i)
{
int color=peg[i].color;
for(int k = 0; k < 8; ++k) //查看八个方位的棋子
{
int x=peg[i].x+xx[k];
int y=peg[i].y+xy[k];
if(x>=0&&x<=n&&y>=0&&y<=n)//边界
{
if(tu[x][y]&&peg[tu[x][y]].color==color)//可以和相同的点连线
{
switch(k)
{
//然后就是每个方位分别判断对应的九条线段就可以了,画好图很简单
case 0:
{
if(link[ tu[x][y-2] ][ tu[x+1][y] ])
break;
if(y-3>=0 && link[ tu[x][y-3] ][ tu[x+1][y-1] ])
break;
if(y+1<=n && link[ tu[x][y-1] ][ tu[x+1][y+1] ])
break;
if(x-1>=0)
{
if(link[ tu[x-1][y-2] ][ tu[x+1][y-1] ])
break;
if(link[ tu[x-1][y-1] ][ tu[x+1][y] ])
break;
if(link[ tu[x-1][y] ][ tu[x+1][y-1] ])
break;
}
if(x+2<=n)
{
if(link[ tu[x+2][y-2] ][ tu[x][y-1] ])
break;
if(link[ tu[x+2][y-1] ][ tu[x][y-2] ])
break;
if(link[ tu[x+2][y] ][ tu[x][y-1] ])
break;
}
int a=tu[peg[i].x][peg[i].y];
int b=tu[x][y];
peg[a].connet[peg[a].cnt++]=b;
peg[b].connet[peg[b].cnt++]=a;
link[a][b]=link[b][a]=1;
break;
}
case 1:
{
if(link[ tu[x][y-1] ][ tu[x+2][y] ])
break;
if(x-1>=0 && link[ tu[x-1][y-1] ][ tu[x+1][y] ])
break;
if(x+3<=n && link[ tu[x+1][y-1] ][ tu[x+3][y] ])
break;
if(y-2>=0)
{
if(link[ tu[x][y-2] ][ tu[x+1][y] ])
break;
if(link[ tu[x+1][y-2] ][ tu[x+2][y] ])
break;
if(link[ tu[x+2][y-2] ][ tu[x+1][y] ])
break;
}
if(y+1<=n)
{
if(link[ tu[x][y-1] ][ tu[x+1][y+1] ])
break;
if(link[ tu[x+1][y-1] ][ tu[x][y+1] ])
break;
if(link[ tu[x+1][y-1] ][ tu[x+2][y+1] ])
break;
}
int a=tu[peg[i].x][peg[i].y];
int b=tu[x][y];
peg[a].connet[peg[a].cnt++]=b;
peg[b].connet[peg[b].cnt++]=a;
link[a][b]=link[b][a]=1;
break;
}
case 2:
{
if(link[ tu[x][y+1] ][ tu[x+2][y] ])
break;
if(x-1>=0 && link[ tu[x-1][y+1] ][ tu[x+1][y] ])
break;
if(x+3<=n && link[ tu[x+1][y+1] ][ tu[x+3][y] ])
break;
if(y-1>=0)
{
if(link[ tu[x][y-1] ][ tu[x+1][y+1] ])
break;
if(link[ tu[x+1][y-1] ][ tu[x][y+1] ])
break;
if(link[ tu[x+2][y-1] ][ tu[x+1][y+1] ])
break;
}
if(y+2<=n)
{
if(link[ tu[x+1][y] ][ tu[x][y+2] ])
break;
if(link[ tu[x+2][y] ][ tu[x+1][y+2] ])
break;
if(link[ tu[x+1][y] ][ tu[x+2][y+2] ])
break;
}
int a=tu[peg[i].x][peg[i].y];
int b=tu[x][y];
peg[a].connet[peg[a].cnt++]=b;
peg[b].connet[peg[b].cnt++]=a;
link[a][b]=link[b][a]=1;
break;
}
case 3:
{
if(link[ tu[x][y+2] ][ tu[x+1][y] ])
break;
if(y-1>=0 && link[ tu[x+1][y-1] ][ tu[x][y+1] ])
break;
if(y+3<=n && link[ tu[x+1][y+1] ][ tu[x][y+3] ])
break;
if(x-1>=0)
{
if(link[ tu[x-1][y] ][ tu[x+1][y+1] ])
break;
if(link[ tu[x-1][y+1] ][ tu[x+1][y] ])
break;
if(link[ tu[x-1][y+2] ][ tu[x+1][y+1] ])
break;
}
if(x+2<=n)
{
if(link[ tu[x][y+1] ][ tu[x+2][y] ])
break;
if(link[ tu[x][y+1] ][ tu[x+2][y+2] ])
break;
if(link[ tu[x][y+2] ][ tu[x+2][y+1] ])
break;
}
int a=tu[peg[i].x][peg[i].y];
int b=tu[x][y];
peg[a].connet[peg[a].cnt++]=b;
peg[b].connet[peg[b].cnt++]=a;
link[a][b]=link[b][a]=1;
break;
}
case 4:
{
if(link[ tu[x-1][y] ][ tu[x][y+2] ])
break;
if(y-1>=0 && link[ tu[x-1][y-1] ][ tu[x][y+1] ])
break;
if(y+3<=n && link[ tu[x-1][y+1] ][ tu[x][y+3] ])
break;
if(x-2>=0)
{
if(link[ tu[x-2][y] ][ tu[x][y+1] ])
break;
if(link[ tu[x-2][y+1] ][ tu[x][y+2] ])
break;
if(link[ tu[x-2][y+2] ][ tu[x][y+1] ])
break;
}
if(x+1<=n)
{
if(link[ tu[x][y] ][ tu[x-1][y+1] ])
break;
if(link[ tu[x+1][y+1] ][ tu[x-1][y] ])
break;
if(link[ tu[x+1][y+2] ][ tu[x-1][y+1] ])
break;
}
int a=tu[peg[i].x][peg[i].y];
int b=tu[x][y];
peg[a].connet[peg[a].cnt++]=b;
peg[b].connet[peg[b].cnt++]=a;
link[a][b]=link[b][a]=1;
break;
}
case 5:
{
if(link[ tu[x-2][y] ][ tu[x][y+1] ])
break;
if(x-3>=0 && link[ tu[x-3][y] ][ tu[x-1][y+1] ])
break;
if(x+1<=n && link[ tu[x-1][y] ][ tu[x+1][y+1] ])
break;
if(y-1>=0)
{
if(link[ tu[x-2][y-1] ][ tu[x-1][y+1] ])
break;
if(link[ tu[x-1][y-1] ][ tu[x][y+1] ])
break;
if(link[ tu[x][y-1] ][ tu[x-1][y+1] ])
break;
}
if(y+2<=n)
{
if(link[ tu[x-1][y] ][ tu[x-2][y+2] ])
break;
if(link[ tu[x-2][y] ][ tu[x-1][y+2] ])
break;
if(link[ tu[x-1][y] ][ tu[x][y+2] ])
break;
}
int a=tu[peg[i].x][peg[i].y];
int b=tu[x][y];
peg[a].connet[peg[a].cnt++]=b;
peg[b].connet[peg[b].cnt++]=a;
link[a][b]=link[b][a]=1;
break;
}
case 6:
{
if(link[ tu[x-2][y] ][ tu[x][y-1] ])
break;
if(x-3>=0 && link[ tu[x-3][y] ][ tu[x-1][y-1] ])
break;
if(x+1<=n && link[ tu[x-1][y] ][ tu[x+1][y-1] ])
break;
if(y-2>=0)
{
if(link[ tu[x-2][y-2] ][ tu[x-1][y] ])
break;
if(link[ tu[x-1][y-2] ][ tu[x-2][y] ])
break;
if(link[ tu[x][y-2] ][ tu[x-1][y] ])
break;
}
if(y+1<=n)
{
if(link[ tu[x-1][y-1] ][ tu[x-2][y+1] ])
break;
if(link[ tu[x][y-1] ][ tu[x-1][y+1] ])
break;
if(link[ tu[x-1][y-1] ][ tu[x][y+1] ])
break;
}
int a=tu[peg[i].x][peg[i].y];
int b=tu[x][y];
peg[a].connet[peg[a].cnt++]=b;
peg[b].connet[peg[b].cnt++]=a;
link[a][b]=link[b][a]=1;
break;
}
case 7:
{
if(link[ tu[x][y-2] ][ tu[x-1][y] ])
break;
if(y-3>=0 && link[ tu[x][y-3] ][ tu[x-1][y-1] ])
break;
if(y+1<=n && link[ tu[x][y-1] ][ tu[x-1][y+1] ])
break;
if(x-2>=0)
{
if(link[ tu[x-2][y-2] ][ tu[x][y-1] ])
break;
if(link[ tu[x-2][y-1] ][ tu[x][y-2] ])
break;
if(link[ tu[x-2][y] ][ tu[x][y-1] ])
break;
}
if(x+1<=n)
{
if(link[ tu[x-1][y-1] ][ tu[x+1][y-2] ])
break;
if(link[ tu[x-1][y-1] ][ tu[x+1][y] ])
break;
if(link[ tu[x-1][y] ][ tu[x+1][y-1] ])
break;
}
int a=tu[peg[i].x][peg[i].y];
int b=tu[x][y];
peg[a].connet[peg[a].cnt++]=b;
peg[b].connet[peg[b].cnt++]=a;
link[a][b]=link[b][a]=1;
break;
}
}
}
}
}
}
bool checkwin()
{
//搜索没什么好说的,最近队列习惯性静态,快但是内存消耗多
for(int k=0;k<=n;k++)
{
int p=tu[0][k];
if(p&&peg[p].color==1)//我们直接搜黑色就好了
{
int q[MAXN];
bool vis[MAXN]={0};
int head=0;
int tail=0;
q[tail++]=p;
vis[p]=1;
while(head<tail)
{
int k=q[head++];
if(peg[k].x==n)
return 1;
for(int i=0;i<peg[k].cnt;i++)
{
int x=peg[k].connet[i];
if(!vis[x])
{
vis[x]=1;
q[tail++]=x;
}
}
}
}
}
return 0;
}