hdu 2416 Treasure of the Chimp Island(bfs求最短路)

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2416


Treasure of the Chimp Island

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 306    Accepted Submission(s): 148

Problem Description
Bob Bennett, the young adventurer, has found the map to the treasure of the Chimp Island, where the ghost zombie pirate LeChimp, the infamous evil pirate of the Caribbeans has hidden somewhere inside the Zimbu Memorial Monument (ZM2). ZM2 is made up of a number of corridors forming a maze. To protect the treasure, LeChimp has placed a number of stone blocks inside the corridors to block the way to the treasure. The map shows the hardness of each stone block which determines how long it takes to destroy the block. ZM2 has a number of gates on the boundary from which Bob can enter the corridors. Fortunately, there may be a pack of dynamites at some gates, so that if Bob enters from such a gate, he may take the pack with him. Each pack has a number of dynamites that can be used to destroy the stone blocks in a much shorter time. Once entered, Bob cannot exit ZM2 and enter again, nor can he walk on the area of other gates (so, he cannot pick more than one pack of dynamites).

The hardness of the stone blocks is an integer between 1 and 9, showing the number of days required to destroy the block. We neglect the time required to travel inside the corridors. Using a dynamite, Bob can destroy a block almost immediately, so we can ignore the time required for it too. The problem is to find the minimum time at which Bob can reach the treasure. He may choose any gate he wants to enter ZM2.
 
Input
The input consists of multiple test cases. Each test case contains the map of ZM2 viewed from the above. The map is a rectangular matrix of characters. Bob can move in four directions up, down, left, and right, but cannot move diagonally. He cannot enter a location shown by asterisk characters (*), even using all his dynamites! The character ($) shows the location of the treasure. A digit character (between 1 and 9) shows a stone block of hardness equal to the value of the digit. A hash sign (#) which can appear only on the boundary of the map indicates a gate without a dynamite pack. An uppercase letter on the boundary shows a gate with a pack of dynamites. The letter A shows there is one dynamite in the pack, B shows there are two dynamite in the pack and so on. All other characters on the boundary of the map are asterisks. Corridors are indicated by dots (.). There is a blank line after each test case. The width and the height of the map are at least 3 and at most 100 characters. The last line of the input contains two dash characters (--).
 
Output
For each test case, write a single line containing a number showing the minimum number of days it takes Bob to reach the treasure, if possible. If the treasure is unreachable, write IMPOSSIBLE.
 
Sample Input
*****#********* *.1....4..$...* *..***..2.....* *..2..*****..2* *..3..******37A *****9..56....* *.....******..* ***CA********** ***** *$3** *.2** ***#* --
 

Sample Output
1 IMPOSSIBLE
 

題意:輸入一個字符矩陣;
   入口:'A'-'Z','#','#'代表不帶炸彈進入,'A'代表帶一個炸彈進入,以此類推
   終點:'$';
   數字代表進過該點有兩種方式,a)炸掉,不付出代價通過;b),花費該數字的代價通過該點
   '.'代表不花費任何代價通過,'*'則代表不能通過

思路:用一個三位數組記錄當前點的狀態,因爲每個數字點可以有兩種方法通過,第三維表示當前點的炸彈數量,此題輸入也值得注意

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define INF 9999999
using namespace std;
struct data
{
    int x,y;
    int bomb;
    int cost;
};
int row;
int col;
char mp[105][105];
int vis[105][105][26];
int result = INF;
int dir[4][2]= {0,1,1,0,-1,0,0,-1};

/*
bool operator<(data a,data b)
{
    return a.cost>b.cost;
}
*/
void bfs()
{
    memset(vis,-1,sizeof(vis));
    int i,j;
    data f;
    queue <data> qu;
    //入口
    for( i =0; i<row; i++)
    {
        for(j=0; j<col; j++)
        {

            if(mp[i][j]=='#' || (mp[i][j]>='A' && mp[i][j]<='Z'))
            {
                f.x=i;
                f.y=j;
                f.cost=0;
                if(mp[i][j]=='#') f.bomb=0;
                else f.bomb = mp[i][j]-'A'+1;
                qu.push(f);
                vis[i][j][f.bomb]=0;
                mp[i][j]='*';
            }
        }
    }
    //搜索
    while(!qu.empty())
    {
        data e;
        f = qu.front();
        qu.pop();
        for(i=0; i<4; i++)
        {
            e.x = f.x+dir[i][0];
            e.y = f.y+dir[i][1];

            if(mp[e.x][e.y]=='*' || e.x<0 || e.y<0 || e.x>=row || e.y>= col)
                continue;

            if(mp[e.x][e.y]=='.') //直接走過,時間不變,炸彈數不變
            {
                e.bomb=f.bomb;
                if(vis[e.x][e.y][e.bomb] == -1 || f.cost < vis[e.x][e.y][e.bomb])
                {
                    e.cost = f.cost;
                    vis[e.x][e.y][e.bomb] = f.cost;
                    qu.push(e);
                }
            }
            else if(mp[e.x][e.y]>='1' && mp[e.x][e.y]<='9')
            {
                //不炸,炸彈不變,時間加上mp[e.x][e.y]
                if(vis[e.x][e.y][f.bomb]==-1 || f.cost+mp[e.x][e.y]-'0' < vis[e.x][e.y][f.bomb])
                {
                    e.bomb = f.bomb;
                    e.cost = f.cost + mp[e.x][e.y]-'0';
                    vis[e.x][e.y][e.bomb]=e.cost;
                    qu.push(e);
                }
                //炸,炸彈數-1,時間不變;
                if(f.bomb>0)
                {
                    if(vis[e.x][e.y][f.bomb-1]==-1 || f.cost < vis[e.x][e.y][f.bomb-1])
                    {
                        e.bomb = f.bomb - 1;
                        e.cost = f.cost;
                        vis[e.x][e.y][e.bomb]=e.cost;
                        qu.push(e);
                    }
                }
            }
            /*else if(mp[e.x][e.y]=='$'&&f.cost<result)
                result = f.cost;*/
            else if(mp[e.x][e.y]=='$' && result > f.cost) //這個地方我找了一下午= =,找到$後,花費應該是前一步的,如果改成e.cost,則結果始終是0;
                result = f.cost;
        }
    }
}
int main()
{
    while(1)
    {
        row=0;
        while(gets(mp[row]))
        {
            if(mp[row][0]=='-')
                return 0;
            if(strlen(mp[row])<1)
                break;
            row++;
        }
        col=strlen(mp[0]);
        result=INF;
        bfs();
        if(result==INF) printf("IMPOSSIBLE\n");
        else printf("%d\n",result);
    }
    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章