您的位置:首页 > 其它

HDU 1010 Tempter of the Bone 经典深搜~DFS

2012-08-16 00:02 357 查看
杭电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:

#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");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  fun system 测试 ini