poj 2706 Connect

7 篇文章 0 订阅

题意:给你一个N+1*N+1的棋盘(从0到N),给定了这局棋的下棋过程,黑子先下,且总的下棋步数为奇数,也就保证最后一个下的是黑棋。其中,每下一步棋如果它的周围(中国象棋或是国际象棋中一个日字的走法)8个点存在同色的棋,并且两个棋之间没有其他棋子连线所拦,那么就将这连个棋子连线。如果黑棋从左边界到右边界有一条线贯穿或白棋从上边界到下边界有一条线贯穿,贯穿的那方就获得胜利。原题意为问黑子的最后一步是否能使得这局棋分出胜负。实际上题意有所差错,在所有棋子下完之后只需要判断是否存在赢家即可(无论黑白)当存在赢家输出yes,黑白均没胜利输出no。

思路:首先必不可少的是判线段是否相交,其次,就是怎么去模拟了。本人用的是完全无脑模拟,就是黑棋一步白棋一步,单独记录黑棋和白棋的每个坐标每当下棋之后就与其他坐标想比对,看看是否在存在8点之一,若存在那么先连线(但不存储)将连线与所有黑白连线比较,看看是否存在相交,当不存在的时候就把黑线存入黑线的存储结构里,白棋同理。最后一遍循环跑完,检查是否有左右或上下贯通。检查联通可使用并查集,将坐标化为一个独立的数值即可。

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define eps 1e-8
#define zero(x) (((x) > 0 ? (x) : (x)) < eps)
using namespace std;

struct Point { double x,y; };
struct Line { Point a,b; };
struct P
{
    int x,y;
};
int arr1[700],arr2[700];
double 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 isIntersected(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.y)) &&
           (max(v.a.y,v.b.y)>=min(u.a.y,u.b.y)) &&
           (xmult(u.a,v.a,u.b)*xmult(u.a,u.b,v.b) > eps)&&
           (xmult(v.a,u.a,v.b)*xmult(v.a,v.b,u.b) > eps);
}
void init()
{
    for(int i=0;i<=700;i++)
    {
        arr1[i]=arr2[i]=i;
    }
}
int Find1(int r)
{
    return r==arr1[r]?r:arr1[r]=Find1(arr1[r]);
}
int Find2(int r)
{
    return r==arr2[r]?r:arr2[r]=Find2(arr2[r]);
}
void Union1(int x,int y)
{
    int fx=Find1(x);
    int fy=Find1(y);
    if(fx!=fy)
    {
        arr1[fx]=fy;
    }
}
void Union2(int x,int y)
{
    int fx=Find2(x);
    int fy=Find2(y);
    if(fx!=fy)
    {
        arr2[fx]=fy;
    }
}
int main()
{
    int n,m;
    int x,y;
    int k;
    while(scanf("%d%d",&n,&m),n||m)
    {
        init();
        int flag;
        int t1=0,t2=0;
        int l1=0,l2=0;
        P p_black[200],p_white[200];
        Line black[200],white[200],line;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&x,&y);
            if(i%2==0){
                for(int j=0;j<t1;j++)
                {
                    flag=0;
                    if((abs(p_black[j].x-x)==2&&abs(p_black[j].y-y)==1)||
                    (abs(p_black[j].x-x)==1&&abs(p_black[j].y-y)==2))
                    {
                        line.a.x=x;
                        line.a.y=y;
                        line.b.x=p_black[j].x;
                        line.b.y=p_black[j].y;
                        for(k=0;k<l2;k++)
                        {
                            if(isIntersected(line,white[k])) {flag=1; break;}
                        }
                        for(k=0;k<l1;k++)
                        {
                            if(isIntersected(line,black[k])) {flag=1; break;}
                        }
                        if(!flag)
                        {
                            black[l1].a.x=line.a.x;
                            black[l1].a.y=line.a.y;
                            black[l1].b.x=line.b.x;
                            black[l1].b.y=line.b.y;
                            l1++;
                            Union1(x*30+y,p_black[j].x*30+p_black[j].y);
                        }
                    }
                }
                p_black[t1].x=x;
                p_black[t1++].y=y;
            }
            else
            {
                for(int j=0;j<t2;j++)
                {
                    flag=0;
                    if((abs(p_white[j].x-x)==2&&abs(p_white[j].y-y)==1)||
                    (abs(p_white[j].x-x)==1&&abs(p_white[j].y-y)==2))
                    {
                        line.a.x=x;
                        line.a.y=y;
                        line.b.x=p_white[j].x;
                        line.b.y=p_white[j].y;
                        for(k=0;k<l2;k++)
                        {
                            if(isIntersected(line,white[k])) {flag=1; break;}
                        }
                        for(k=0;k<l1;k++)
                        {
                            if(isIntersected(line,black[k])) {flag=1; break;}
                        }
                        if(!flag)
                        {
                            white[l2].a.x=line.a.x;
                            white[l2].a.y=line.a.y;
                            white[l2].b.x=line.b.x;
                            white[l2].b.y=line.b.y;
                            l2++;
                            Union2(x*30+y,p_white[j].x*30+p_white[j].y);
                        }
                    }
                }
                p_white[t2].x=x;
                p_white[t2++].y=y;
            }
        }
        flag=0;
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=n;j++)
            {
                if(Find1(i)==Find1(n*30+j)||Find2(i)==Find2(n*30+j)){
                    printf("yes\n");
                    flag=1;
                    break;
                }
            }
            if(flag) break;
        }
        if(!flag) printf("no\n");
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值