POJ 2706 棋盘连线游戏(模拟)

POJ 2706

题目大意

黑棋从x轴0连到N算胜利,白棋从y轴0连到N算胜利
让你判断黑棋最后一步是否胜利
具体见原网页
这里写图片描述

分析

对于线采用两种存放方式:
一种用四维数组实现,便于询问两点间是否有线
另一种用结构体实现,方便对线的集合进行操作
最后用BFS判断各个线的联通分量是否有跨越两边边界的

连线的时候是不能与其他线之间有交集的,这道题的关键就是如何判断一条线连下去是否会产生交集。

这道题我按着一开始的思路写了后发现问题越来越多,感觉就在不断打补丁,纠结了几个小时后还是换了看似最暴力的方法但思路要清晰了许多。
说一下一开始复杂的而且还没改对的思路:
一开始认为只要一条线连上了这条线所占的两个格子就都不能再放了,所以就用用了一个数组标记上,后面出现WA测数据才发现还有下图左边的情况,然后就单独处理了这种情况,之后有发现还有下图右边的情况,感觉就是在不断打补丁,最后该完了觉得没问题了数据也过不了,不知道哪里的问题实在没办法还是放弃了。。。
这里写图片描述

后面还是按照枚举的方法来判断可能出现交集的边
这里写图片描述

总结

以后做模拟题一定要仔细想好思路了再开始写。
还有就是如果写了一段时间发现方法很繁琐一定要敢于放弃这个方法,补不过来的方法及时换。
这几天模拟题真是写伤了,还好这个是最后道了。

代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
using namespace std;
int N,M;
int cover[30][30];//cover[x][y]表示(x,y),值为0表示没有被边覆盖,1表示黑边覆盖,2表示白边覆盖
int line[30][30][30][30];//判断(xa,ya)到(xb,yb) 1黑边 2b白边
int node[30][30];//node[x][y]为1表示黑点,2表示白点
int nodebj[30][30];
int bj[30][30][30][30];//Check时搜过的边标记上
int xx[8]={-2,-1,1,2,2,1,-1,-2};
int yy[8]={1,2,2,1,-1,-2,-2,-1};
struct LINE
{
    int xa;int ya;
    int xb;int yb;
}line1[2005];
int cnt_line1;
bool Is_out(int x,int y)
{
      if(x>=0 && x<=N && y>=0 && y<=N)return 0;
      else return 1;
}
bool  Is_line(int xx1,int yy1,int xx2,int yy2)
{
    if(xx1<0 || xx1 >N || yy1<0 || yy1>N || xx2 <0 || xx2>N || yy2<0 || yy2>N)return 0;
    if(line[xx1][yy1][xx2][yy2]==0)return 0;
    return 1;
}
void Add_node(int x,int y,int color)
{
      node[x][y]=color;
      int flag;
      for(int i=0;i<8;i++)//8个方向寻找能连上线的点
      {
           int tx=x+xx[i];
           int ty=y+yy[i];
           if(Is_out(tx,ty))continue;
           int flag=0;//0表示能放
           int xx1,yy1,xx2,yy2;
           if(node[tx][ty]==color )
           {
               if(abs(tx-x)==1 && (tx-x)*(ty-y)<0)
               {
                   xx1=min(tx,x);yy1=max(ty,y);
                   xx2=max(tx,x);yy2=min(ty,y);
                   if(Is_line(xx1-1,yy1,xx2,yy2+1)){flag=1;}
                   if(Is_line(xx1,yy1-1,xx2+1,yy2)){flag=1;}
                   if(Is_line(xx1-1,yy1-1,xx2,yy2+2)){flag=1;}
                   if(Is_line(xx1,yy1-1,xx2+1,yy2+2)){flag=1;}
                   if(Is_line(xx1-1,yy1-2,xx2,yy2+1)){flag=1;}
                   if(Is_line(xx1,yy1-2,xx2+1,yy2+1)){flag=1;}
                   if(Is_line(xx1,yy1-1,xx2,yy2+3)){flag=1;}
                   if(Is_line(xx1,yy1-2,xx2,yy2+2)){flag=1;}
                   if(Is_line(xx1,yy1-3,xx2,yy2+1)){flag=1;}
               }
               else if(abs(tx-x)==1 && (tx-x)*(ty-y)>0)
               {
                   xx1=min(tx,x);yy1=min(ty,y);
                   xx2=max(tx,x);yy2=max(ty,y);
                   if(Is_line(xx1-1,yy1,xx2,yy2-1)){flag=1;}
                   if(Is_line(xx1,yy1+1,xx2+1,yy2)){flag=1;}
                   if(Is_line(xx1,yy1+1,xx2,yy2-3)){flag=1;}
                   if(Is_line(xx1,yy1+2,xx2,yy2-2)){flag=1;}
                   if(Is_line(xx1,yy1+3,xx2,yy2-1)){flag=1;}
                   if(Is_line(xx1-1,yy1+1,xx2,yy2-2)){flag=1;}
                   if(Is_line(xx1,yy1+1,xx2+1,yy2-2)){flag=1;}
                   if(Is_line(xx1-1,yy1+2,xx2,yy2-1)){flag=1;}
                   if(Is_line(xx1,yy1+2,xx2+1,yy2-1)){flag=1;}
               }
               else if(abs(tx-x)==2 && (tx-x)*(ty-y)<0)
               {
                    xx1=min(tx,x);yy1=max(ty,y);
                   xx2=max(tx,x);yy2=min(ty,y);
                   if(Is_line(xx1,yy1+1,xx2-1,yy2)){flag=1;}
                   if(Is_line(xx1+1,yy1,xx2,yy2-1)){flag=1;}
                   if(Is_line(xx1-1,yy1-1,xx2-1,yy2+1)){flag=1;}
                   if(Is_line(xx1,yy1-1,xx2,yy2+1)){flag=1;}
                   if(Is_line(xx1+1,yy1-1,xx2+1,yy2+1)){flag=1;}
                   if(Is_line(xx1,yy1-1,xx2-1,yy2+2)){flag=1;}
                   if(Is_line(xx1,yy1-2,xx2-1,yy2+1)){flag=1;}
                   if(Is_line(xx1+1,yy1-1,xx2,yy2+2)){flag=1;}
                   if(Is_line(xx1+1,yy1-2,xx2,yy2+1)){flag=1;}
               }
               else if(abs(tx-x)==2 && (tx-x)*(ty-y)>0)
               {
                    //if(x==4 && y==3 && tx==2 && ty==2)cout<<"a"<<endl;
                    xx1=min(tx,x);yy1=min(ty,y);
                    xx2=max(tx,x);yy2=max(ty,y);
                   if(Is_line(xx1,yy1-1,xx2-1,yy2)){flag=1;}
                   if(Is_line(xx1+1,yy1,xx2,yy2+1)){flag=1;}
                   if(Is_line(xx1-1,yy1+1,xx2-1,yy2-1)){flag=1;}
                   if(Is_line(xx1,yy1+1,xx2,yy2-1)){flag=1;}
                   if(Is_line(xx1+1,yy1+1,xx2+1,yy2-1)){flag=1;}
                   if(Is_line(xx1,yy1+1,xx2-1,yy2-2)){flag=1;}
                   if(Is_line(xx1,yy1+2,xx2-1,yy2-1)){flag=1;}
                   if(Is_line(xx1+1,yy1+1,xx2,yy2-2)){flag=1;}
                   if(Is_line(xx1+1,yy1+2,xx2,yy2-1)){flag=1;}
               }
               if(flag==1)continue;
               //(x,y)(tx,ty)能放
               line[x][y][tx][ty]=color;
               line[tx][ty][x][y]=color;
              // if(color==1)cout<<"("<<x<<","<<y<<") ("<<tx<<","<<ty<<")"<<endl;
               if(color==1)//如果是黑边就保存下来
               {
                     //cout<<max(tx,x)<<" "<<max(ty,y)<<" "<<min(tx,x)+1<<" "<<min(ty,y)+1<<endl;
                     line1[++cnt_line1].xa=x;
                     line1[cnt_line1].ya=y;
                     line1[cnt_line1].xb=tx;
                     line1[cnt_line1].yb=ty;
               }
           }
      }
}
void Travel()
{
     for(int y=N;y>=0;y--)
     {
           for(int x=0;x<=N;x++)
           {
                 cout<<cover[x][y];
           }
           cout<<endl;
     }

     for(int i=1;i<=cnt_line1;i++)
     {
           cout<<"("<<line1[i].xa<<","<<line1[i].ya<<") ("<<line1[i].xb<<","<<line1[i].yb<<")"<<endl;
     }
}
void Bfs(int x,int y,int &end0,int &endN)
{
      memset(nodebj,0,sizeof(nodebj));
      queue<int> Qx;
      queue<int> Qy;
      Qx.push(x);
      Qy.push(y);
      nodebj[x][y]=1;
      while(!Qx.empty())
      {
          x=Qx.front();Qx.pop();
          y=Qy.front();Qy.pop();
          for(int i=0;i<8;i++)
          {
               int tx=x+xx[i];
               int ty=y+yy[i];
               if(Is_out(tx,ty))continue;//判断是否出界
               if(nodebj[tx][ty]==0 && line[x][y][tx][ty]==1)
               {
                    nodebj[tx][ty]=1;
                    if(tx==0)end0=1;
                    if(tx==N)endN=1;
                    Qx.push(tx);
                    Qy.push(ty);
               }
          }
      }

}
bool Check()
{
    int xa,ya,xb,yb;
    int end0,endN;
    for(int i=1;i<=cnt_line1;i++)//从每条边开始进行BFS
    {
         xa=line1[i].xa;
         ya=line1[i].ya;
         end0=0;endN=0;
         if(nodebj[xa][ya]==1)continue;
         if(xa==0)end0=1;
         if(xa==N)endN=1;
         Bfs(xa,ya,end0,endN);
         if(end0==1 && endN==1)return 1;
    }
    return 0;
}
void Init()
{
      memset(cover,0,sizeof(cover));
      memset(node,0,sizeof(node));
      memset(line,0,sizeof(line));
      memset(bj,0,sizeof(bj));
      cnt_line1=0;
}
int main()
{
     int x,y;
     while(scanf("%d%d",&N,&M)!=EOF)
     {
           Init();
           if(N==0 && M==0)break;
           for(int i=1;i<=M;i++)
           {
                 scanf("%d%d",&x,&y);
                 if(i%2==1)Add_node(x,y,1);
                 else Add_node(x,y,2);
           }
           //Travel();
           if(Check()==1)cout<<"yes"<<endl;
           else cout<<"no"<<endl;
     }
    return 0;
}

功能简介 “易行辅助”试用版是把“易行象棋连线器试用版”每次5分钟自动连接,以方便试用,还增加了 时间查看等小功能。 “易行辅助”正式版是把“易行象棋连线器试用版”的限时和限次“取消”,增加了计时等小功能。 此辅助每5分钟会自动(亦可手动,右键点此程序的托盘图标选择)初始化一次,此时请勿操作。 注意:试用版只能用75分钟,正式版要注册才能使用!!!! 易行简介 易行象棋连线器是一款棋软及象棋游戏的辅助工具软件,其采用独特的棋盘识别方法,能连过去许多连线不能连的网站,如:JJ中国象棋、越南象棋网、大师网、面对面、同城游戏、中游、联众等。该连线支持多种棋软连线自动下棋,如:天机、旋风、兵河 五四、奇兵、大圣等象棋软件。该软件能随时对任意局面进行连接,能人机操作。可以遮挡棋软和客户端界面。 目前已通过测试的象棋游戏:JJ中国象棋、QQ新中国象棋、QQ旧中国象棋(角色版)、大师网、奕天棋缘、金游世界、同城游、面对面、泓弈象棋网、中游、联众。 使用说明 1、试用版限制使用15次,每次时间5分钟,本辅助会把15次自动连接,可连续使用(共75分钟)1次。 试用版界面上方显示的是每次使用的时间,鼠标右键点本“辅助”托盘图标可以查看剩余时间。 2、正式版界面上方显示的是“辅助”程序运行时间,无使用次数限制,亦无时长限制。正式版要注 册才能使用,联系QQ:48377000。 3、退出本“辅助”,请使用鼠标右键点击本“辅助”右下图标的“退出” 注意事项 1、为了快速上手,如果你使用兵河界面,请使用“系统默认兵河方案界面图”中相同的界面, 系统默认兵河方案是兵河初始的棋盘和底图,小棋子,这样可以不需要做方案直接的连线。 2、“JJ金色赛场自动打擂.exe”注册后才能使用,建议在正常走棋后再打开此工具,不能关闭 “赛场展示:金色娱乐场”窗口。鼠标右键点此程序的托盘图标,有相关功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值