poj2706

Connect
Time Limit: 1000MS Memory Limit: 65536K
Total 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). 

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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值