1. 程式人生 > >HNUST 挑戰ACM迷宮(DFS版)

HNUST 挑戰ACM迷宮(DFS版)

題目描述

如下圖所示的是一個由程式設計題目組成的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,當然也可以BFS,甚至DP。dfs有4個方向,採用記憶化搜尋,記錄每一個點的最短路路徑,當然,這樣還是會超時。再網dfs引數中加一個sum,表示當前的步數,如果大於ans就終止。最後要注意,要把迷宮中的0設為不可以走的牆壁,別設定為一個很大的數,否則dfs還是會搜尋下去。

#include <bits/stdc++.h>

using namespace std;

int n;
int z[110][110];
int vis[110][110];
int dir[4][2]={1,0,0,1,-1,0,0,-1};
int ans;
void dfs(int x,int y,int sum)//加一個sum是用來剪枝的
{
    if(x==n && y==n)//到達終點
    {
        ans=sum;
        return ;
    }
    if(sum>ans) return ;//當前這點的和已經大於終點的了,直接剪去
    for(int i=0;i<4;i++)
    {
        int xx,yy;
        xx=x+dir[i][0];
        yy=y+dir[i][1];
        if(xx>=1 && yy>=1 && x<=n && yy<=n && z[xx][yy]!=0)
        {
            if(vis[xx][yy]==-1)//該點沒被訪問過
            {
                vis[xx][yy]=z[xx][yy]+vis[x][y];
                dfs(xx,yy,vis[xx][yy]);
            }
            else if(vis[xx][yy]>z[xx][yy]+vis[x][y])//該點被訪問過了,但是不是最優
            {
                vis[xx][yy]=z[xx][yy]+vis[x][y];
                dfs(xx,yy,vis[xx][yy]);
            }

        }
    }
}
int main()
{
    while(scanf("%d",&n)==1)
    {
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
            {
               scanf("%d",&z[i][j]);
                vis[i][j]=-1;
            }
        vis[1][1]=z[1][1];
        ans=100000;
        dfs(1,1,z[1][1]);
        printf("min=%d\n",vis[n][n]);//ans和vis[n][n]是一樣的
    }

    return 0;
}