HNUST 挑战ACM迷宫(DFS)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xMaii/article/details/75429921

题目描述
如下图所示的是一个由程序设计题目组成的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;
}

猜你喜欢

转载自blog.csdn.net/xMaii/article/details/75429921