Connect
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
/* 题目大意
题意描述没看清楚,看了题解之后更模糊了,所以打算写一个正规一点的题意.
题目的大意是给一个n*n的棋盘,但由于存在0点所以真正的棋盘点数有(n+1)*(n+1).
然后再依次给出m组棋子的坐标,黑棋先手。然后在棋盘上放下一个棋子的前提是这个点上之前没有棋子,相同颜色的棋子可以相互连接起来,连接的方式是按照“日”字的八个方向,也就是说,如果这个棋子的周围八个方向上有棋子的话,就可以连接起来了放一颗棋子也许会出现多条线段可连,那就全部连上.
关键点是如果黑棋在棋盘上可以在横方向上(即x轴方向)一直连接到n,判赢。或者相反,白棋在棋盘上可以在纵方向上(即y轴方向)一直连接到n,判赢.
连接的时候注意不管是黑线段还是白线段一律不可以相交.
最后的结果意思是问在m组棋子都放完时有没有分出胜负,如果在所有棋子放完之前分出胜负了,输出yes,否则就是no.
*/
/*解题思路
先把所有的棋子坐标都存起来,初始化棋盘,一个一个的放棋子,注意标记棋子是黑还是白。放的时候把这个棋子可以连接的所有线段都连接上。每放完一个棋子就判断一下棋盘最左边和最下边有没有出现棋子,如果出现了棋子,就直接bfs去搜,搜到为n的情况,跳到最后,否则继续放棋子。
*/
<pre name="code" class="html">#include <algorithm> #include <iostream> #include <numeric> #include <cstring> #include <iomanip> #include <string> #include <vector> #include <cstdio> #include <queue> #include <stack> #include <cmath> #include <map> #include <set> #define LL long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int M = 300; const double esp = 1e-8; const int INF = 0x3f3f3f3f; const double PI = 3.141592653589793; using namespace std; struct Point{ int x,y; bool friend operator ==(Point a,Point b){ return (a.x == b.x && a.y == b.y); } }Point_arr[300]; struct Line{ Point a,b; }arr[250*250]; int n,m,top; int Map[30][30]; int dx[] = {-1,-2,-2,-1,1,2,2,1}; int dy[] = {-2,-1,1,2,2,1,-1,-2}; bool vis[30][30]; bool flag; int 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 isx(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.x)) && (max(v.a.y,v.b.x) >= min(u.a.y,u.b.y)) && (xmult(u.a,v.a,u.b)*xmult(u.a,u.b,v.b) > esp) && (xmult(v.a,u.a,v.b)*xmult(v.a,v.b,u.b) > esp); } //加一颗棋子 void build(int x,int y,int type){ if(Map[x][y] == -1){ Map[x][y] = type; for(int i=0;i<8;i++){ int nowx = x + dx[i]; int nowy = y + dy[i]; if(nowx >=0 && nowx <= n && nowy >= 0 && nowy <= n && Map[nowx][nowy]!=-1 && Map[nowx][nowy] == Map[x][y]){ Line ant;ant.a = {x,y};ant.b = {nowx,nowy}; bool flag = true; for(int j=0;j<top;j++){ if(isx(arr[j],ant)){ flag = false; break; } } if(flag){ arr[top++] = ant; } } } } } //判断线段有没有被连接起来过 bool f(int x,int y,int u,int v){ for(int i=0;i<top;i++){ if((arr[i].a.x == x && arr[i].a.y == y && arr[i].b.x == u && arr[i].b.y == v) || (arr[i].b.x == x && arr[i].b.y == y && arr[i].a.x == u && arr[i].a.y == v) ) return true; } return false; } //黑棋的bfs void b_bfs(int y){ memset(vis,false,sizeof(vis)); queue<Point>Q; Q.push({0,y}); vis[0][y] = true; while(!Q.empty()){ Point ant = Q.front();Q.pop(); if(ant.x == n){ flag = true; break; } for(int i=0;i<8;i++){ int nowx = ant.x + dx[i]; int nowy = ant.y + dy[i]; if(nowx >=0 && nowx <= n && nowy >= 0 && nowy <= n && !vis[nowx][nowy] && Map[nowx][nowy]!=-1 && f(ant.x,ant.y,nowx,nowy)){ vis[nowx][nowy] = true; Q.push({nowx,nowy}); } } } } //白棋的bfs void w_bfs(int x){ memset(vis,false,sizeof(vis)); queue<Point>Q; Q.push({x,0}); vis[x][0] = true; while(!Q.empty()){ Point ant = Q.front();Q.pop(); if(ant.y == n){ flag = true; break; } for(int i=0;i<8;i++){ int nowx = ant.x + dx[i]; int nowy = ant.y + dy[i]; if(nowx >=0 && nowx <= n && nowy >= 0 && nowy <= n && !vis[nowx][nowy] && Map[nowx][nowy]!=-1 && f(ant.x,ant.y,nowx,nowy)){ vis[nowx][nowy] = true; Q.push({nowx,nowy}); } } } } int main(){ while(~scanf("%d %d",&n,&m) && (n||m)){ top = 0; flag = false; memset(Map,-1,sizeof(Map)); for(int i=1;i<=m;i++) scanf("%d %d",&Point_arr[i].x,&Point_arr[i].y); for(int i=1;i<=m;i++){ build(Point_arr[i].x,Point_arr[i].y,i%2); //黑1 白2 for(int j=0;j<=n;j++){ if(Map[0][j]!=-1){ b_bfs(j); } if(flag) break; } if(flag) break; for(int j=0;j<=n;j++){ if(Map[j][0]!=-1){ w_bfs(j); } } } if(flag) printf("yes\n"); else printf("no\n"); } return 0; }