题目地址:点击打开链接
思路:普通回溯要超时,用到奇偶减枝,网上资料比较多,说我的理解:判断起点到终点的最短步数,无论偏移几格,偏移的步数一定为偶数,所以最短走的路和要走的路奇偶性相同,所以他们的和或差就相同,不相同就可以直接回溯;
AC代码:
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;
char lol[8][8];
int starti,startj,endi,endj,t,flag;
int x[4] = {0,-1,0,1}, y[4] = {-1,0,1,0};
void dfs(int a,int b,int l)
{
if(flag)
return;
if(l > t)
return;
int i,temp;
temp = t - l + abs(a-endi) + abs(b-endj);
if(a==endi && b==endj && l==t)
{
flag = 1;
return;
}
if(temp & 1)
{
return;
}
for(i=0; i<4; i++)
{
a += x[i];
b += y[i];
if(lol[a][b] != 'X')
{
lol[a][b] = 'X';
dfs(a,b,l+1);
lol[a][b] = '.';
}
a -= x[i];
b -= y[i];
}
}
int main()
{
memset(lol,'X',sizeof(lol));
int n,m,i,j,sum;
while(scanf("%d%d%d",&n,&m,&t))
{
sum = 0;
flag = 0;
if(n==0 && m==0 && t==0)
break;
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
{
cin>>lol[i][j];
if(lol[i][j] == 'S')
{
starti = i;
startj = j;
}
else if(lol[i][j] == 'D')
{
endi = i;
endj = j;
}
else if(lol[i][j] == 'X')
sum++;
}
lol[starti][startj] = 'X';
if(n*m-sum-1>=t)
dfs(starti,startj,0);
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}