题目大意:除了不能出界,其余就像玩游戏一样.
思路:有几个注意的地方:
(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;}