POJ 2706

Idea:

record points and add edges during input.

check whether an edge can be added by calculating intersection point of two lines and find out if the intersection point is within the line segments. (see solution())

Since no winning is guatanteed before last point. so after complete input, using dfs to check whether points are connect and cover the whole range of x axis for black player.

 

 

// Accepted	312K	16MS
#include<iostream>
#include<vector>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
int N,M;
int dir[8][2]={{-1,2},{-1,-2},{-2,-1},{-2,1},{1,-2},{1,2},{2,-1},{2,1}};


struct Point
{
    bool black;//true is black is placed here
    bool white;
    int x;
    int y;
    vector<Point> adjp;
    int visited;
}P[21][21];
class Edge
{
public:
    Point a;
    Point b;
    int color;//0 for white, 1 for black
};
vector<Edge> vec;
void init()
{
    for(int i=0;i<21;i++)
    {
        for(int j=0;j<21;j++)
        {
            P[i][j].black=false;
            P[i][j].white=false;
            P[i][j].adjp.clear();
            P[i][j].visited=0;
        }
    }
}
bool inRange(int x)
{
    return x>=0&&x<=N;
}
void solution(float a,float b,float c,float d,float e,float f,float &x1,float &x2)
{
    float det=a*d-b*c;
    x1=(e*d-b*f)/det;
    x2=(a*f-e*c)/det;
}
bool between(float mid,int a,int b)
{
    return mid>min(a,b)&&mid<max(a,b);
}
bool intersect(int x,int y,int newx,int newy)
{
    for(vector<Edge>::iterator ite=vec.begin();ite!=vec.end();ite++)
    {
        int x1=P[x][y].x,y1=P[x][y].y,x2=P[newx][newy].x,y2=P[newx][newy].y;
        int m1=ite->a.x,n1=ite->a.y,m2=ite->b.x,n2=ite->b.y;
        float s1,s2;
        solution(y1-y2,x2-x1,n1-n2,m2-m1,-x1*y2+x2*y1,-m1*n2+m2*n1,s1,s2);
        //printf("(%d,%d) (%d,%d)    (%d,%d) (%d,%d) s1=%f s2=%f bool=%d %d %d %d\n",x1,y1,x2,y2,m1,n1,m2,n2,s1,s2,(int)(between(s1,x1,x2)),(int)(between(s1,m1,m2)),(int)(between(s2,y1,y2)),(int)(between(s2,n1,n2)));
        if(between(s1,x1,x2)&&between(s1,m1,m2)&&between(s2,y1,y2)&&between(s2,n1,n2))
        {
            //printf("x=%d y=%d newx=%d newy=%d intersect=true\n",x,y,newx,newy);
            return true;
        }
    }
    //printf("x=%d y=%d newx=%d newy=%d intersect=false\n",x,y,newx,newy);
    return false;
}
void dfs(int x,int y,bool &meetleft,bool &meetright)
{   
    //printf("in dfs x=%d y=%d\n",x,y);
    if(x==0)
    {
        meetleft=true;
    }
    if(x==N)
    {
        meetright=true;
    }
    if(meetleft&&meetright)
    {
        //cout<<"return in advance"<<endl;
        return;
    }
    for(vector<Point>::iterator ite=P[x][y].adjp.begin();ite!=P[x][y].adjp.end();ite++)
    {
        if(ite->visited==0)
        {
            ite->visited=1;
            dfs(ite->x,ite->y,meetleft,meetright);
        }
        
    }
}
bool complete(int x,int y)
{
    bool meetleft=false;
    bool meetright=false;
    dfs(x,y,meetleft,meetright);
    return meetleft&&meetright;
}
int main()
{
    //freopen("result.txt","w",stdout);
    int x,y;
    int newx,newy;
    for(int i=0;i<21;i++)
    {
        for(int j=0;j<21;j++)
        {
            P[i][j].x=i;
            P[i][j].y=j;
        }
    }
    while(1)
    {
        init();
        vec.clear();
        scanf("%d%d",&N,&M);
        if(N==0&&M==0)
        {
            break;
        }
        //bool precondition;
        for(int i=0;i<M;i++)
        {   
            scanf("%d%d",&x,&y);
            if(i%2==0)//black
            {
                P[x][y].black=true;
                for(int k=0;k<8;k++)
                {
                    newx=x+dir[k][0];
                    newy=y+dir[k][1];
                    if(inRange(newx)&&inRange(newy)&&P[newx][newy].black==true)
                    {
                        //printf("x=%d y=%d newx=%d newy=%d\n",x,y,newx,newy);
                        if(!intersect(x,y,newx,newy))
                        {
                            Edge e;
                            e.a=P[x][y];
                            e.b=P[newx][newy];
                            e.color=1;
                            vec.push_back(e);
                            //printf("x=%d y=%d newx=%d newy=%d is pushed\n",x,y,newx,newy);
                            P[x][y].adjp.push_back(P[newx][newy]);
                            P[newx][newy].adjp.push_back(P[x][y]);
                            //printf("x=%d y=%d connect newx=%d newy=%d\n",x,y,newx,newy);
                        }
                    }
                }
                if(i==M-1)
                {
                    cout<<((complete(x,y))? "yes" : "no")<<endl;
                }
            }
            else
            {
                P[x][y].white=true;
                for(int k=0;k<8;k++)
                {
                    newx=x+dir[k][0];
                    newy=y+dir[k][1];
                    if(inRange(newx)&&inRange(newy)&&P[newx][newy].white==true)
                    {
                        if(!intersect(x,y,newx,newy))
                        {
                            Edge e;
                            e.a=P[x][y];
                            e.b=P[newx][newy];
                            e.color=0;
                            vec.push_back(e);
                            
                            //printf("x=%d y=%d newx=%d newy=%d (white)is pushed\n",x,y,newx,newy);
                        }
                    }
                }
            }
        }

        
    }

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值