链接:
hduoj 1253:http://acm.hdu.edu.cn/showproblem.php?pid=125
nyoj 523:http://acm.nyist.net/JudgeOnline/problem.php?pid=523
在杭电上看不懂题的可以到nyoj看看,简单说一下题意,定义一个数组map [ 60] [60 ] [60 ] ,如果存放输入数据不是从数组的下标0 开始,3个地方都是从下标 1 开始。就是求map [ 1 ][ 1 ][ 1 ] 到 map [ A ] [ B ][ C ] 的最短时间。题目中要求是0为路,1为墙。。每次可以向相邻的 6 个方位走,如果可以到达目的地,求出最短时间。。然后在和T比较,然后........就不用我说了吧。。
说说我的思路吧:广度优先搜索,搜索过程中,搜过的点标记,下次遇到不再搜索,每组输入数据都初始化map数组为0,存放输入数据是从下标1开始,题目中0为路,1为墙,我们改为1为路,0为墙。。为什么这样呢?狠简单,这样相当于在输入数据边上加上一层0,即一层墙。。这样你就不用担心越界的问题了,而且这样做,不需要剪枝在hduoj nyoj 就能ac。。(后台数据比较弱。nyoj现在正在修改后台数据,就是卡我的那个没剪枝的代码,O(∩_∩)O哈哈~),但是不这样做,你若没剪枝你可能就会超时。。
再说一下怎么剪枝,想一想:
(1)如果 目的地 map[ A ] [ B ] [ C ]是墙,你就根本到不了,所以直接输出-1,不用再搜索了。。
(2)如果 都是路,木有墙,最短时间为A+B+C,木有错吧,如果此时最短时间>T,直接输出-1,没必要搜索了。。
具体思路就这些了,有问题或者更好思路的欢迎讨论交流,哈哈。。
贴一下代码:
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int kj[]={0,0,0,0,1,-1},sx[]={0,0,1,-1,0,0},zy[]={1,-1,0,0,0,0};
int map[60][60][60],ac[60][60][60];
int n,m,w,t;
struct hello
{
int x,y,z,step;
};
void bfs()
{
int a,b,x,y,z,sum,loop=0;
queue<hello>Q;
hello ok1={1,1,1,0};
Q.push(ok1);
ac[1][1][1]=1;
while(!Q.empty())
{
x=Q.front().x;
y=Q.front().y;
z=Q.front().z;
sum=Q.front().step;
Q.pop();
if(x==w&&y==n&&z==m)
{loop=1;break;}
for(a=0;a<6;a++) //向相邻6个方向搜索
{
int i=x+kj[a];
int j=y+sx[a];
int p=z+zy[a];
if(ac[i][j][p]==0&&map[i][j][p]==1)
{
hello ok2={i,j,p,sum+1};
Q.push(ok2);
ac[i][j][p]=1;
}
}
}
if(sum<=t&&loop==1)
printf("%d\n",sum);
else
printf("-1\n");
}
int main()
{
int a,b,c,k,kkk;
scanf("%d",&k);
while(k--)
{
memset(ac,0,sizeof(ac));//用来标记该点是否走过
memset(map,0,sizeof(map));
scanf("%d %d %d %d",&w,&n,&m,&t);
for(c=1;c<=w;c++)
for(a=1;a<=n;a++)
for(b=1;b<=m;b++)
{
scanf("%d",&kkk);
if(kkk==0) //转换
map[c][a][b]=1;
else
map[c][a][b]=0;
}
if(map[w][n][m]==0||w+n+m>t)//剪枝。。
{printf("-1\n");continue;}
bfs();
}
}