题目:http://acm.hdu.edu.cn/showproblem.php?pid=1072
题目描述:矩阵表示迷宫,0表示墙,1表示路,2表示起点,3表示终点,4表示重置炸弹时间(6秒),你需要从起点出发(炸弹初始为6秒),在炸弹爆炸前到达终点,问最少需要多少时间。
分析:dfs,可以走走过的路,所以不能使用vis数组来标记,而是用dis和tim两个数组来帮助判断所走路线,通过这两个数组的记录来剪枝(此处剪枝:当sum大于dis[x][y]且time<=tim[x][y]说明当前这条路并非最佳路线,此处着重理解)。
总结:dfs摸到的些许门道,还需加强,剪枝还需要多见识一些。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define INF 100 int map[10][10]; int dir[4][2]= {{-1,0},{0,1},{1,0},{0,-1}}; int dis[10][10]; int tim[10][10]; int n,m,minx; bool inside(int x,int y) { if(x<n&&x>=0&&y<m&&y>=0) return 1; return 0; } void dfs(int x,int y,int time,int sum) { if(map[x][y]==3&&time>0) { if(sum<minx) minx=sum; return; } if(time<=0) return; if(map[x][y]==0) return; if(!inside(x,y)) return; if(time<=tim[x][y]&&sum>=dis[x][y]) //剪枝 return; if(map[x][y]==4) time=6; dis[x][y]=sum; tim[x][y]=time; for(int i=0; i<4; i++) { int mx=x+dir[i][0]; int my=y+dir[i][1]; dfs(mx,my,time-1,sum+1); } } int main() { int t,sx,sy,ex,ey; scanf("%d",&t); while(t--) { memset(tim,0,sizeof(tim)); minx=INF; scanf("%d%d",&n,&m); for(int i=0; i<n; i++) for(int j=0; j<m; j++) dis[i][j]=INF; for(int i=0; i<n; i++) for(int j=0; j<m; j++) { scanf("%d",&map[i][j]); if(map[i][j]==2) { sx=i; sy=j; } } dfs(sx,sy,6,0); if(minx!=INF) printf("%d\n",minx); else printf("-1\n"); } return 0; }
时间: 2024-10-09 05:22:40