1. 程式人生 > >HDU2128 (dfs)Tempter of the Bone II

HDU2128 (dfs)Tempter of the Bone II

The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze was changed and the way he came in was lost.He realized that the bone was a trap, and he tried desperately to get out of this maze.


The maze was a rectangle with the sizes of N by M. The maze is made up of a door,many walls and many explosives. Doggie need to reach the door to escape from the tempter. In every second, he could move one block to one of the upper, lower, left or right neighboring blocks. And if the destination is a wall, Doggie need another second explode and a explosive to explode it if he had some explosives. Once he entered a block with explosives,he can take away all of the explosives. Can the poor doggie survive? Please help him.InputThe input consists of multiple test cases. The first line of each test case contains two integers N, M,(2 <= N, M <= 8). which denote the sizes of the maze.The next N lines give the maze layout, with each line containing M characters. A character is one of the following: 

'X': a block of wall; 
'S': the start point of the doggie; 
'D': the Door; 
'.': an empty block; 
'1'--'9':explosives in that block. 

Note,initially he had no explosives. 

The input is terminated with two 0's. This test case is not to be processed. 
OutputFor each test case, print the minimum time the doggie need to escape if the doggie can survive, or -1 otherwise.Sample Input
4 4
SX..
XX..
....
1..D
4 4
S.X1
....
..XX
..XD
0 0
Sample Output
-1
9

題意:此題要求從S走到D,'X'是牆,'.'是路,'1'到'9'是炸彈的數量,牆可以消耗一個炸彈炸掉,同時需要1個單位的時間來安放炸彈,問所花費的最少時間是多少;

思路:地圖不大,炸彈的數量也不多,所以開一個3維的標記陣列vis,vis[i][j][k]表示座標i,j,所攜帶的炸彈數量為k時,是否走過;

同時再開個輔助陣列用來剪枝,詳情看程式碼:

#include<bits/stdc++.h>
using namespace std;
char s[10][10];
bool vis[10][10][640];
typedef pair<int,int>P;
P v[10][10];//記錄到座標x,y的最短時間和炸彈數量
int n, m, l;
int d[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
void dfs(int x, int y, int z, int zt) {
    //cout<<x<<" "<<y<<" "<<z<<" "<<zt<<endl;
    if(s[x][y] == 'D') {
        if(z < l)
            l = z;
        return ;
    }
    if(z >= l) {
        return ;
    }
    if(v[x][y].first>z){//有更優解更新答案
        v[x][y].first=z;
        v[x][y].second=zt;
    }
    else if(v[x][y].first<z){//時間花的多還炸彈少肯定是不需要的
        if(zt<=v[x][y].second)return ;
    }
    else if(v[x][y].first==z){//時間相同,炸彈也相同說明重複了,炸彈少的話說明有更優狀態不要繼續搜下去
        if(v[x][y].second<zt)v[x][y].second=zt;
        else return ;
    }
    for(int i = 0; i < 4; i++) {
        int xx = x + d[i][0];
        int yy = y + d[i][1];
        if(xx < 0 || xx >= n || yy < 0 || yy >= m)
            continue;
        if(vis[xx][yy][zt])
            continue;
        vis[xx][yy][zt] = 1;
        if(s[xx][yy] == '.' || s[xx][yy] == 'D' || s[xx][yy] == 'S') {
            dfs(xx, yy, z + 1, zt);
        }
        if(s[xx][yy] == 'X') {
            if(zt>0) {
                vis[xx][yy][zt - 1] = 1;
                s[xx][yy] = '.';
                dfs(xx, yy, z + 2, zt - 1);
                s[xx][yy] = 'X';
                vis[xx][yy][zt - 1] = 0;
            }
        }
        if(s[xx][yy] >= '1' && s[xx][yy] <= '9') {
            int a = s[xx][yy] - '0';
            vis[xx][yy][zt + a] = 1;
            s[xx][yy] = '.';
            dfs(xx, yy, z + 1, zt + a);
            vis[xx][yy][zt + a] = 0;
            s[xx][yy] = '0' + a;
        }
        vis[xx][yy][zt] = 0;
    }
    return ;
}
int main() {
    while(scanf("%d%d", &n, &m) == 2) {
        if(n == m && n == 0)
            break;
        l = 1000000000;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            v[i][j].first=1000000000,v[i][j].second=0;
        for(int i = 0; i < n; i++)
            scanf("%s", s[i]);
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                if(s[i][j] == 'S') {
                    vis[i][j][0] = 1;
                    dfs(i, j, 0, 0);
                }
        if(l!=1000000000)printf("%d\n",l);
        else printf("-1\n");
    }
    return 0;
}