HDU1175 连连看 DFS

题目大意:除了不能出界,其余就像玩游戏一样.

思路:有几个注意的地方:

(1)如果是给出同一点的判断能否抵消的,答案应该是否

(2)如果两点不相等的话也不行

(3)如果两点都是0的话也不行

我是用DFS做得,一开始TLE,后来有一个犀利的剪枝,200ms.NICE.

剪枝就是考虑在成功之前的状态:如果转折数已经达到2,但是还没有到达目的地,这应该要跳出.(成功与失败就在一线之差!)

我是这样判断拐角的:建立两个拐角变量,记录未开始拐角的坐标lastx,lasty,如果出现拐角的话,条件就是:x!=lastx&&y!=lasty,这样就可以拐角叠加了,另外更新一下当前的拐角坐标即可.

 

AC Program:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm> 
#include<string.h>
using namespace std;
int n,m;
int mapp[1010][1010]; 
int flag[1010][1010];
int q;
int s1,t1,s2,t2;
int tk;//拐角数量 
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int lastx,lasty;//拐角的坐标变量 
int dfs(int a,int b)
{
  if(a==s2&&b==t2&&tk<=2)
     return 1;
  if(tk==2&&a!=s2&&b!=t2)
     return 0;
  for(int i=0;i<4;i++)
  {
     int tx=a+dir[i][0];
     int ty=b+dir[i][1];
     //路上除了碰到终点的数字之外,其余的都是路障 
     if(tx>=1&&tx<=n && ty>=1&&ty<=m && (!mapp[tx][ty] || tx==s2&&ty==t2) &&!flag[tx][ty])//mapp[tx][ty]写成tyty了,次奥! 
     {
     //开始计算拐角 ,如果拐角了,修改拐角坐标,并叠加,超过2的拐角不D下去,
     //反之,D下去,
     //没有发生拐角的同样可以D下去 
         if(tx!=lastx && ty!=lasty && tk<2)
            {
               tk++;
               int tmpx=lastx,tmpy=lasty;
               lastx=tx,lasty=ty;
               flag[tx][ty]=1; 
               if(dfs(tx,ty)==1)
                  return 1;
                tk--;
                lastx=tmpx,lasty=tmpy;
                flag[tx][ty]=0;
                            
            }            
         else if(tx==lastx || ty==lasty)
            {
                flag[tx][ty]=1; 
               if(dfs(tx,ty)==1)
                  return 1;
                flag[tx][ty]=0;             
            } 
     }        
  }
  return 0;    
}
int main()
{
while(~scanf("%d%d",&n,&m)&&(n||m))
{
   for(int i=1;i<=n;i++)
     {
       for(int j=1;j<=m;j++)
         {
           scanf("%d",&mapp[i][j]); 
           flag[i][j]=0;     
         }      
     }
   scanf("%d",&q);
   for(int i=0;i<q;i++)
   {
      scanf("%d%d%d%d",&s1,&t1,&s2,&t2);
      //判断特殊情况
      if(mapp[s1][t1]!=mapp[s2][t2] || (s1==s2 && t1==t2) || mapp[s1][t1]==0&&mapp[s2][t2]==0)
        {
          printf("NO\n");
          continue;                             
        }
      memset(flag,0,sizeof(flag));
      tk=0;
      lastx=s1,lasty=t1;//一开始的拐角坐标就是起始坐标 
      if(dfs(s1,t1)==1)
          printf("YES\n");
      else
          printf("NO\n");
   }             
   
}
//system("pause");
return 0;} 


 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值