杭电1010
dfs杭电1010
这道经典的dfs剪枝例题引出奇偶剪枝:
先看ac码:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
int a,b,c,x,y,zx,zy;
char s[10][10];
int zb[]= {-1,1,0,0},yb[]= {0,0,1,-1};
int flag=0;
void dfs(int l,int r,int num) {
if(l==zx&&r==zy&&num==c)
{
flag=1;
return ;
}
if(flag==1) return ;
int f=abs(zx-l)+abs(zy-r);
if(f%2!=(c-num)%2)return ;
for(int i=0; i<4; i++) {
int ll=l+zb[i];
int rr=r+yb[i];
if(s[ll][rr]!='X' && ll<=a && ll>=1&& rr<=b && rr>=1&&num<=c) {
s[ll][rr]='X';
dfs(ll,rr,num+1);
s[ll][rr]='.';
}
}
}
int main() {
while(scanf("%d %d %d",&a,&b,&c)&& a+b+c!=0) {
memset(s,'\0',sizeof(s));
for(int i=1; i<=a; i++)
{
scanf("%s", s[i] + 1);
for(int j=1; j<=b; j++)
{
if(s[i][j]=='S') {
x=i;
y=j;
}
if(s[i][j]=='D') {
zx=i;
zy=j;
}
}
}
s[x][y]='X';
flag=0;
dfs(x,y,0);
if(flag==1)
printf("YES\n");
else printf("NO\n");
}
}
剪枝过程如下:
意思就是从a点到b点
他们之间的路程最短是:
x=|x1-x2|+|y1-y2|
但是只要是从a点到b点路程一定是x+2n
因为如何一段从a到b的路程一定是从最短路的路线平移再进行加路线的
但是从横竖方向来看进行的路程加减次数一定是二的倍数,因为向左对应向右
有一个左就一定有一个又,所以可以用来判断,如果求余数不相等那么一定不满足条件
。