杭电 2128 Tempter of the Bone II(广搜)bfs+优先队列+伴随map

Tempter of the Bone II

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 98304/32768 K (Java/Others)
Total Submission(s): 1960    Accepted Submission(s): 510


Problem Description
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.
 

Input
The 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.
 

Output
For 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
 

Author
XHD
 
无力吐槽...............................................
这里先上大牛给的数据:希望对读者找bug有帮助:
数据源自:http://blog.csdn.net/mnlm1991/article/details/5919971

6 6
S1XX3X
XXXXXX
2XXXXX
XXXXXX
XXXXXX
X1XDXX
29

 

5 3
S..
1X.
XX.
...
XXD

6

 


5 6
S.XXXX
21..XX
XXXXXX
XXXXXX
3XXXDX

11


6 5
S.XX1
X.1X1
XX.X.
XXXXX
XXXXX
XXXDX

对于这个题真的是无力吐槽,这个题目有几个难点:

1.vis数组不能再是普通的二维数组

2.不能在原来的地图上炸X.需要用结构体伴随一个map

3.使用优先队列,炸X的方式有很多,我们不得不借用优先队列的特性来完成题目.

思路很清晰,遇到炸弹就放在兜兜里,然后炸弹的地方变成‘.’,遇到‘.’就直接走上去,遇到'X'就炸一下子(要是没有就不炸)

思路很简单,代码实现却是充满了坑,各种坑。大坑。

废话不啰嗦,这里直接上代码:

#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
struct node
{
    int x,y,num,step;
    char mp[15][15];//伴随map(这里不能在原图上炸X)
    bool friend operator<(node a,node b)
    {
        return a.step>b.step;
    }
} t;
int dir[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};
char s[15][15];
int vis[15][15][55];
int n,m,ex,ey,flag;
int bfs(int x,int y)
{
    priority_queue<node>q;
    int i,j;
    for(i=0; i<n; i++)
        for(j=0; j<m; j++)
            t.mp[i][j]=s[i][j];//图的copy
    t.step=0;
    t.num=0;
    t.x=x;
    t.y=y;
    vis[t.x][t.y][0]++;
    q.push(t);
    while(!q.empty())
    {
        t=q.top();
        if(t.x==ex && t.y==ey)
            return t.step;
        for(i=0; i<4; i++)//下边的思路还是比较清晰的.
        {
            t.step++;
            t.x+=dir[i][1];
            t.y+=dir[i][0];
            if(t.x>=0 && t.x<n && t.y>=0 && t.y<m && vis[t.x][t.y][t.num]<100)//最多也就重复走100次
            {
                if(t.mp[t.x][t.y]=='.')
                {
                    vis[t.x][t.y][t.num]++;
                    q.push(t);
                }
                else if(t.mp[t.x][t.y]=='X' && t.num>0)
                {
                    vis[t.x][t.y][t.num]++;
                    t.step++;
                    t.num--;
                    t.mp[t.x][t.y]='.';
                    q.push(t);
                }
                else if(t.mp[t.x][t.y]>='1' && t.mp[t.x][t.y]<='9')
                {
                    vis[t.x][t.y][t.num]++;
                    t.num+=t.mp[t.x][t.y]-'0';
                    t.mp[t.x][t.y]='.';
                    q.push(t);
                }
            }
            t=q.top();
        }
        q.pop();
    }
    return -1;
}
int main()
{
    int i,j,x1,y1;
    while(~scanf("%d%d",&n,&m) && n)
    {
        for(i=0; i<n; i++)
            scanf("%s",s[i]);
        for(i=0; i<n; i++)
            for(j=0; j<m; j++)
            {
                if(s[i][j]=='S')
                {
                    s[i][j]='.';
                    x1=i,y1=j;
                }
                else if(s[i][j]=='D')
                {
                    s[i][j]='.';
                    ex=i,ey=j;
                }
            }
        memset(vis,0,sizeof vis);
        printf("%d\n",bfs(x1,y1));
    }
}






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值