链接:
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(); } }