HDU 2416 Treasure of the Chimp Island (BFS)

来源:互联网 发布:好听的淘宝会员名 文艺 编辑:程序博客网 时间:2024/06/05 20:34

问题描述:
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,B,C。。。呢,就是进入地图的入口,只能从这些字母的地方进入地图,并且字母A代表不但是个门,这个门里面还有炸药,代表有1包炸药,B代表两包炸药,依次类推。’#‘也代表门,但是这个门里面没有炸药。你从一扇门里面进去,就不能从其他门里面捡炸药了。’*‘代表墙,不能过,’.’代表路,可以走,并且走这种路不需要耗费时间,数字1到9代表石头,你经过这些石头要耗费1到9的时间,你也可以不费时间,直接耗费一包炸药。问最短时间到达宝藏。

思路分析:
挺好的一道bfs的题。
首先,因为起点是不确定的。所以我们要遍历每一个起点。走一遍bfs,这里做的优化就是。a[x][y][k],代表,走到(x,y)这个点的时候,携带k个炸药包。所需的最小步数。
其实我觉得这里有点像记忆化搜索,但又有点不一样。
如果这个状态出现过或者需要的步数比这个多,那么我们就没必要再将这种状态入队了。

ac代码:

#include<stdio.h>#include<iostream>#include<queue>#include<string.h>#include<algorithm>#include<stdlib.h>#include<cstring>#include<string>#define N 20000000using namespace std;int n,m,ss;//ss用于存最小时间int a[105][105][30];//状态数组,第3维是带的炸药个数,前2个是坐标。string map[105];int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//用于变换坐标struct node{    int x,y;    int k,time;//k是携带的炸药包,time是到这里所花的时间    //重载<运算符,用于优先队列的实现    friend bool operator < (const node a,const node b)    {        return a.time>b.time;    }}w,v;priority_queue<node> q;bool check(int x,int y)//边境检查{    if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='*')        return 1;    return 0;}void bfs(){    memset(a,-1,sizeof(a));    for(int i=0;i<n;i++)//找出所有的门并加入队列    {        for(int j=0;j<m;j++)        {            if(map[i][j]=='#')            {                w.x=i;w.y=j;                w.time=0;w.k=0;                map[i][j]='*';                q.push(w);            }            else if(map[i][j]>='A'&&map[i][j]<='Z')            {                w.x=i;w.y=j;                w.time=0;                w.k=map[i][j]-'A'+1;  //炸弹数。                map[i][j]='*';                q.push(w);            }        }    }    while(!q.empty())    {        v=q.top();        q.pop();        for(int i=0;i<4;i++)        {            w.x=v.x+dir[i][0];            w.y=v.y+dir[i][1];            if(!check(w.x,w.y))                continue;            if(map[w.x][w.y]=='.')//如果是路,直接走过去            {                w.k=v.k;                //如果携带w.k个炸药在x,y点的状态没有检查过                //或者以前的走法没有现在的走法优                if(a[w.x][w.y][w.k]==-1||a[w.x][w.y][w.k]>v.time)                {                    w.time=v.time;                    a[w.x][w.y][w.k]=w.time;                    q.push(w);                }            }            else if(map[w.x][w.y]>='1'&&map[w.x][w.y]<='9')            {                //炸这个石头                if(v.k>0&&(a[w.x][w.y][v.k-1]==-1||a[w.x][w.y][v.k-1]>v.time))                {                    w.k=v.k-1;                    w.time=v.time;                    a[w.x][w.y][w.k]=w.time;                    q.push(w);                }                //不炸这个石头                if(a[w.x][w.y][v.k]==-1||a[w.x][w.y][v.k]>v.time+map[w.x][w.y]-'0')                {                    w.k=v.k;                    w.time=v.time+map[w.x][w.y]-'0';                    a[w.x][w.y][w.k]=w.time;                    q.push(w);                }            }            else if(map[w.x][w.y]=='$'&&v.time<ss)            {                ss=v.time;            }        }    }}int main(){    while(getline(cin,map[0])&&map[0][0]!='-')    {        int i=1;        while(getline(cin,map[i])&&map[i].size()!=0)            i++;        n=i;        m=map[0].size();        ss=N;    //最短时间。        bfs();        if(ss==N)            printf("IMPOSSIBLE\n");        else            printf("%d\n",ss);    }    return 0;}
0 0
原创粉丝点击