HNUST 挑战ACM迷宫(DFS)

来源:互联网 发布:55度杯好用吗 知乎 编辑:程序博客网 时间:2024/05/21 11:46

题目描述
如下图所示的是一个由程序设计题目组成的ACM迷宫。迷宫的左上角是入口,右下角是出口。迷宫中每一个格子都有一个程序设计题目,挑战者要AC该题目后才能通过,大于0的数字表示AC该题目所需的最短时间。数字如果是0表示是陷阱,进去了就出不来。现在的问题是:求挑战者从入口到出口所需的最短时间。

输入
有多组测试实例。
对于每组测试实例,先输入一个数字n(1< n <= 100),然后输入n*n个数字表示迷宫中的数字。

输出
对应输出挑战者从入口到出口所需的最短时间。

样例输入
10
1 0 2 1 2 3 4 2 2 5
2 1 0 1 3 2 5 7 2 1
1 1 1 0 1 1 1 3 2 3
1 2 1 1 0 1 1 1 2 3
1 1 2 0 2 0 2 3 2 3
2 2 2 2 3 2 0 2 3 2
3 2 2 2 1 1 1 0 1 1
0 1 1 3 0 1 1 2 3 2
2 0 1 1 2 2 2 2 2 2
3 2 3 2 3 2 3 2 3 2
5
1 2 1 2 5
1 3 2 4 5
2 1 0 2 5
2 1 1 2 1
2 4 1 1 2

样例输出
min=29
min=11

这道题用dfs+剪枝求解。剪枝在三个方面:
1. 用数组vis[i][j]进行记忆化搜索,不再访问已访问过的点;
2. 如果走到终点前的任意某点时,花费的时间已经比已知的最短总时要多,则剪掉;
3. 用数组dp[x][y]来更新每次走到点(x,y)时所花费的最短时间,若此次路线来到点(x,y)花费的时间比原来的还多,那么这种方案必然不是最优;
代码如下。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXSIZE = 101;int map[MAXSIZE][MAXSIZE], vis[MAXSIZE][MAXSIZE], dp[MAXSIZE][MAXSIZE];int n, ans;const int dx[] = { 0,1,-1,0 };const int dy[] = { 1,0,0,-1 };void init_map(){    memset(vis, 0, sizeof(vis));    memset(dp, 0x7f, sizeof(dp));   //设为无穷大值    for (int i = 1; i <= n; i++)        for (int j = 1; j <= n; j++)            scanf("%d", &map[i][j]);}bool In(int x, int y)   //判断点(x,y)是否合法{    if (x<1 || x>n || y<1 | y>n)        return false;    return true;}void dfs(int x, int y, int time)    //(x,y)是当前位置的坐标,time是已花费时间{    if (x == n&&y == n)             //到达终点    {        ans = min(time + map[x][y], ans);   //更新最短时间        return;    }    if (time >= ans || time >= dp[x][y]) return;    //剪枝,1.当前花费的时间已经大于最短总时;2.本次来到当前点花费的时间比原来的多    dp[x][y] = time;    for (int i = 0; i < 4; i++)    {        if (In(x + dx[i], y + dy[i]) && map[x][y] != 0 && !vis[x + dx[i]][y + dy[i]])        {            vis[x + dx[i]][y + dy[i]] = 1;  //标记点(x,y)为已访问状态            dfs(x + dx[i], y + dy[i], time + map[x][y]);            vis[x + dx[i]][y + dy[i]] = 0;  //还原        }    }}int main(){    while (scanf("%d", &n) != EOF)    {        init_map();        ans = 0x7ffffff;        vis[1][1] = 1;        dfs(1, 1, 0);        printf("min=%d\n", ans);    }    return 0;}
原创粉丝点击