杭电1010题经典的深搜问题 值得一看~~
解释
一.奇偶剪枝
例如 4*4的矩阵
1 0 1 0
0 1 0 1
1 0 10
0 1 0 1
由1到1 由0到0必走偶数步
由1到0 由0到1必走偶数步
所以 根据这个和时间来判断是否成立
例如
4 4 5
S . X .
. . X .
. . X .
D . . .
代码:
int dis=abs(bx-ex)+abs(by-ey);
if((dis+t)%2!=0){printf("NO\n");continue;} //奇偶剪枝
S处于1的位置 D处于0的位置 则必须经历奇数的步骤才可以到达 3,5,7,都可以 到达
如果给的时间是4,6一定不行
二:位置剪枝
nx>=0&&nx<n&&ny>=0&&ny<m
即所给的查找位置不能超过地图的范围
三:
dis>t-time
剩余的时间到达不了既定的位置;
如
4 4 3
.S X .
. . X .
. . X .
.D . .
就会排除向左走的情况
如果想左走
dis=4 t=3 time由0变成了1 会减掉这种情况。
四 切记切记要对 代码中我用红线标注的注意 一定要重新进行初始化
如果不重新初始化 还用x,y的话会对其产生影响 是带入子函数的值变化。
正确代码:
post code:

解释
一.奇偶剪枝
例如 4*4的矩阵
1 0 1 0
0 1 0 1
1 0 10
0 1 0 1
由1到1 由0到0必走偶数步
由1到0 由0到1必走偶数步
所以 根据这个和时间来判断是否成立
例如
4 4 5
S . X .
. . X .
. . X .
D . . .
代码:
int dis=abs(bx-ex)+abs(by-ey);
if((dis+t)%2!=0){printf("NO\n");continue;} //奇偶剪枝
S处于1的位置 D处于0的位置 则必须经历奇数的步骤才可以到达 3,5,7,都可以 到达
如果给的时间是4,6一定不行
二:位置剪枝
nx>=0&&nx<n&&ny>=0&&ny<m
即所给的查找位置不能超过地图的范围
三:
dis>t-time
剩余的时间到达不了既定的位置;
如
4 4 3
.S X .
. . X .
. . X .
.D . .
就会排除向左走的情况
如果想左走
dis=4 t=3 time由0变成了1 会减掉这种情况。
四 切记切记要对 代码中我用红线标注的注意 一定要重新进行初始化
如果不重新初始化 还用x,y的话会对其产生影响 是带入子函数的值变化。
正确代码:
post code:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int n,m,t,bx,by,ex,ey,flag=0;;
char map[10][10];
int visit[10][10];
int dx[4]={-1,0,0,1},dy[4]={0,-1,1,0};
void dfs(int x,int y,int time)
{
int i;
if(flag==1){return;} //查找成功后返回
if(time==t){if(x==ex&&y==ey){flag=1;return;}} //在给定的时间时找到出口
if(t<=time){return;} //超出时间未找到 放弃
int dis;
dis=abs(ex-x)+abs(ey-y); //查找的位置 与终点的距离
if((dis>t-time)||(dis+t-time)%2!=0)
//1是剩余的时间到不了既定位置 2是运动中奇偶 剪枝
{return;} //上一句话是关键的剪枝
for(i=0;i<4;i++)
{ int nx=x+dx[i]; //切记一定要重新定义查找的地点 keykeykey
int ny=y+dy[i];
if(nx>=0&&nx<n&&ny>=0&&ny<m&&visit[nx][ny]!=1&&map[nx][ny]!='X')
{
//前四个 位置剪枝 第五个 不走返回路 第六个 不走障碍路
visit[nx][ny]=1; //标记已经过
dfs(nx,ny,time+1); //注意营卫time+1 time++是错误的
visit[nx][ny]=0; //将经过 回溯为 未经过
}
}
}
int main()
{ int i,j,temp,dis,ji;
while(scanf("%d %d %d",&n,&m,&t))
{
ji=1;
for(i=0;i<10;i++) //对visit数组进行初始化
for(j=0;j<10;j++)
visit[i][j]=0;
if(n==0&&m==0&&t==0)break;
for(i=0;i<n;i++)
{
scanf("%s",map[i]);
for(j=0;j<m;j++)
{
if(map[i][j]=='S'){bx=i;by=j;} //找到入口位置
if(map[i][j]=='D'){ex=i;ey=j;} //找到出口的位置
if(map[i][j]=='.'){ji++;} //记录可行路的个数
}
}
if(ji<t){printf("NO\n");continue;} //可行路的个数小于时间 不行
int dis=abs(bx-ex)+abs(by-ey);
if((dis+t)%2!=0){printf("NO\n");continue;} //奇偶剪枝
flag=0;
visit[bx][by]=1;
dfs(bx,by,0);
if(flag==1)printf("YES\n"); //正确找到结果
else printf("NO\n"); //为找到结果
}
}
下附自己的测试样例
4 4 5
S.X.
..X.
..XD
....
NO
3 4 5
S.X.
..X.
...D
YES
3 4 10
S...
..X.
..D.
YES
3 4 6
....
..X.
.SXD
YES
对四的解释
样例
post code:
#include<stdio.h>
#include<stdlib.h>
void fun(int t)
{
printf("t=%d\n",t);
int i,nt;
if(t==2)return;
for(i=1;i<=3;i++)
{ int nt=t+1;
fun(nt);
}
}
int main()
{
fun(0);
system("pause");
}
如果我想要的结果是这个:
#include<stdio.h>
#include<stdlib.h>
void fun(int t)
{
printf("t=%d\n",t);
int i;
if(t==2)return;
for(i=1;i<=3;i++)
{
fun(t++); //这里会逐渐改变t的值,因为他包含两步份 加一和赋值不会得到上面想要的结果
//若改成t+1和上面的结果一样
}
}
int main()
{
fun(0);
system("pause");
}