Connect
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1390 | Accepted: 472 |
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
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #define MAXN 25 #define MAXM 255 int N = 0; int M = 0; //AC了,但是最关键的线段相交是我看网上的,这个要再看下 int postion[8][2] = { { 2, 1 }, { 1, 2 }, { -1, 2 }, { -2, 1 }, { -2, -1 }, { -1, -2 }, { 1, -2 }, { 2, -1 } }; //思路 //1:首先要连线 然后是找到最后一个点后是否有符合条件的,如果有,还要剔除掉最后一个点,看是否有符合条件的 //对于怎么连线,自己没什么思路 typedef struct peg { int color; int x; int y; int connect[8];//和这个相连的点, 比如当前是点1,然后connect记的5 6 8,说明1->5 1->6 1->8 int conx[8]; int cony[8]; int num; //记这个点和多少点相连 }pegs; int marix[MAXN][MAXN]; //记棋子的编号 pegs qizi[MAXN*MAXN]; int link[MAXM][MAXM];//记哪些棋子相连,按编号连接 int lastx = 0; int lasty = 0; typedef struct Dians { int x; int y; }Dian; typedef struct Lines { Dian a; Dian b; }Line; void init() { int i = 0; int j = 0; int k = 0; int m = 0; for (i = 0; i < MAXN;i++) { for (j = 0; j < MAXN; j++) { marix[i][j] = 0; qizi[k].color = 0; qizi[k].x = 0; qizi[k].y = 0; qizi[k].num = 0; for (m = 0; m < 8;m++) { qizi[k].connect[m] = 0; qizi[k].conx[m] = 0; qizi[k].cony[m] = 0; } k++; } } for (i = 0; i < MAXM; i++) { for (j = 0; j < MAXM; j++) { link[i][j] = 0; } } return; } int Min(int a, int b) { return a>b ? b : a; } int Max(int a, int b) { return a>b ? a : b; } int chaji(Dian p1, Dian p2, Dian p0) { return (p1.x - p0.x)*(p2.y - p0.y) - (p1.y - p0.y)*(p2.x - p0.x); } int across(Line m, Line n) { if (Min(m.a.x, m.b.x) <= Max(n.a.x, n.b.x) && Min(n.a.x, n.b.x) <= Max(m.a.x, m.b.x) && Min(m.a.y, m.b.y) <= Max(n.a.y, n.b.y) && Min(n.a.y, n.b.y) <= Max(m.a.y, m.b.y) && chaji(m.a, n.b, n.a)*chaji(m.b, n.b, n.a)<0 && chaji(n.a, m.b, m.a)*chaji(n.b, m.b, m.a)<0) return 1; else return 0; } int check(int index, int x2, int y2) { int i = 0; int j = 0; int startx1 = qizi[index].x; int starty1 = qizi[index].y; int startx2 = x2; int starty2 = y2; int endx1 = 0; int endy1 = 0; int endx2 = 0; int endy2 = 0; Line m; Line n; m.a.x = startx1; m.a.y = starty1; m.b.x = startx2; m.b.y = starty2; for (i = 0; i < index;i++) { for (j = 0; j < qizi[i].num;j++) //依次看已有的线段和现在的线段是否相交 { endx1 = qizi[i].x; endy1 = qizi[i].y; endx2 = qizi[i].conx[j]; endy2 = qizi[i].cony[j]; n.a.x = endx1; n.a.y = endy1; n.b.x = endx2; n.b.y = endy2; //开始判断 if (1 == across(m, n)) { return 0; } } } return 1; } void line(int index, int clor) { int i = 0; int x1 = 0; int y1 = 0; //要找8个方向有没有同颜色的棋子,然后有没有线段存在 for (i = 0; i < 8;i++) { x1 = qizi[index].x + postion[i][0]; y1 = qizi[index].y + postion[i][1]; if (x1<0 || x1 > N || y1<0 || y1> N) continue; if (0 == marix[x1][y1]) continue; //没有棋子 if (clor != qizi[marix[x1][y1]].color) continue; //颜色不一样 if (1 == link[index][marix[x1][y1]]) continue; //已经相连 //下面就要判断线段是否相交 //这个是有公式的 if (0 == check(index,x1,y1)) { //有线段相交,看下一个点 continue; } qizi[index].connect[qizi[index].num] = marix[x1][y1]; qizi[index].conx[qizi[index].num] = x1; qizi[index].cony[qizi[index].num] = y1; qizi[index].num += 1; qizi[marix[x1][y1]].connect[qizi[marix[x1][y1]].num] = marix[qizi[index].x][qizi[index].y]; qizi[marix[x1][y1]].conx[qizi[marix[x1][y1]].num] = qizi[index].x; qizi[marix[x1][y1]].cony[qizi[marix[x1][y1]].num] = qizi[index].y; qizi[marix[x1][y1]].num += 1; link[marix[qizi[index].x][qizi[index].y]][marix[x1][y1]] = 1; link[marix[x1][y1]][marix[qizi[index].x][qizi[index].y]] = 1; } return; } int BFS(int last) { int head = 0; int end = 0; int index = 0; int i = 0; int j = 0; int p = 0; int step[MAXM] = { 0 }; int visit[MAXM] = { 0 }; if (1 != last) { index = M; } //起点是(0,*) for (i = 0; i <= N;i++) { p = marix[0][i]; if (0 == p) continue; if (index == p) continue; if (1 != qizi[p].color) continue; //如果不是黑棋子 step[end] = p; visit[p] = 1; end += 1; while (head < end) { if (N == qizi[step[head]].x) { return 1; //找到一条线 } for (j = 0; j < qizi[step[head]].num;j++) { if (visit[qizi[step[head]].connect[j]]) continue; if (index == qizi[step[head]].connect[j]) continue; //如果这次要剔除掉最后一个点 step[end] = qizi[step[head]].connect[j]; visit[qizi[step[head]].connect[j]] = 1; end += 1; } head += 1; } } return 0; } //最后一步连成一条线才算赢 int main() { int i = 0; int x = 0; int y = 0; freopen("input.txt","r",stdin); while (scanf("%d %d",&N,&M)) { lastx = 0; lasty = 0; if ((0 == N) && (0 == M)) break; init(); for (i = 1; i <= M; i++) { scanf("%d %d",&x,&y); marix[x][y] = i; //给点编号 qizi[i].x = x; qizi[i].y = y; if (0 == (i%2)) { qizi[i].color = 0;//白棋 } else { qizi[i].color = 1;//黑棋 } if (i == M) { lastx = x; lasty = y; } //同颜色的线段也不能相交 line(i,qizi[i].color);//开始连接图形 } //开始测最后一个黑色棋子是否能连成一条线 if (1 == BFS(1)) { //没有最后一个点看是否能连成一条线 if (0 == BFS(0)) { printf("yes\n"); } else { printf("no\n"); } } else { printf("no\n"); } } return 0; }