1009

题目标号:1009

题目大意:连连看。给你一个数组表示地图,0表示空,给N组2对坐标,判断是否可以消去,只能从中间空的过,不能从外面走。

解题思路:这题是个复杂的深搜,主要难度在于如何剪枝判断。我们先这样想,一个人走路,在空地上走,他可以往前后左右四个方位,他需要到达离他有段距离的某地。他应该                        先判断那点在他的什么方向上,然后有2种方法:先走再拐弯或者先拐弯再走。标记一下他拐弯的次数,可以发现,他拐第3次就相当于往回走了,那就更不要考虑更多                      的次数了。如果理解这种情况,那可以考虑这题了。首先,数组存地图,然后给2对坐标,先判断是不是2个不同的坐标和地图上两个点数值是不是相同,可以提前结                          束。创建个标记的数组,进行储存是否走过的路。开始深搜。深搜的4个参数分别是,X1的横坐标,X1的纵坐标,a是指拐弯次数,b是标记上次的方向看是否与下次相                            同,相同就不用在拐弯次数加1,不同的话就加1次。在函数里,有许多剪枝:拐弯大于等于3,越界,正好到目标点等。最后如果还没有找到就标记回来,也就是退回                       来选另一个路。退出函数再进行外循环。

做题感想:第一次遇到这种剪枝,很不容易想,最主要的还是因为自己做题少了,见识少了。做题也是拓展眼界的重要方法。

#include<iostream>
#include<cstring>
using namespace std;
int map[1001][1001],N,M,x1,x2,y1,y2;
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
int arr[1001][1001],i,j;
bool f;
void dfs(int x,int y,int a,int b)
{
     if(f)
         return;
     if(a>=3)
         return;
     if(x==x2&&y==y2)
     {
         f=true;
         return;
     }
     if(x<0||y<0||x>=N||y>=M||map[x][y]!=0||arr[x][y])
         return;
     if(a==2)
     {
         if(!(b==0&&y2==y&&x2<x||b==1&&y2==y&&x2>x||b==2&&y2<y&&x2==x||b==3&&y2>y&&x2==x))
             return;
     }
     arr[x][y]=1;
    for(i=0;i<4;i++)
     {
         if(i==b)
             dfs(x+dx[i],y+dy[i],a,b);
         else
             dfs(x+dx[i],y+dy[i],a+1,i);
     }
     arr[x][y]=0;
 }
int main()
 {
    int n;
     while(cin>>N>>M&&(N||M))
     {
         for(i=0;i<N;i++)
             for(j=0;j<M;j++)
               cin>>map[i][j];
         cin>>n;
         while(n--)
         {
            cin>>x1>>y1>>x2>>y2;
             x1--;
             x2--;
             y1--;
             y2--;
             f=false;
             if((x1!=x2||y1!=y2)&&(map[x1][y1]==map[x2][y2])&&map[x1][y1]!=0)
             {
                 memset(arr,0,sizeof(arr));
                 arr[x1][y1]=1;
                 for(i=0;i<4;i++)
                     dfs(x1+dx[i],y1+dy[i],0,i);
             }
             if(f)
               cout<<"YES"<<endl;
             else
              cout<<"NO"<<endl;
         }
     }
     return 0;
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值