poj2706
来源:互联网 发布:软件版本号是什么 编辑:程序博客网 时间:2024/06/08 05:59
Connect
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 1359 Accepted: 452
Description
Figure 1Figure 2Figure 3aFigure 3bFigure 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).
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 50 2 2 4 4 2 3 2 2 34 50 2 2 4 4 2 3 2 2 17 110 3 6 5 3 2 5 7 7 2 4 45 3 5 2 4 5 4 0 2 40 0
Sample Output
noyesyes優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;}
0 0
- poj2706
- POJ2706
- poj2706 connect
- poj2706麦森数
- poj2706 connect
- poj2706-麦森数-高精度快速幂
- POJ2706 Connect(并查集+模拟)
- UVA 11549 Calculator Conundrum(floyd判圈法+两种速度慢的一般写法)
- rabbitmq技术的一些感悟(二)
- Android自定义view之余额不同状态显示
- 一个简单的c语言程序实现两个整数求最大公约数
- 一下午的努力终于可以自由上网
- poj2706
- Windows下Python安装OpenCV详细步骤
- 结束UiAutomator 进程
- 二叉树前序、中序、后序遍历(Java递归版)
- Java中的逆变与协变
- 网站架构的演进
- opencv——插值
- 【Java集合源码剖析】ArrayList源码剖析
- 用vue+webpack搭建的前端项目结构