UVALive 5006 (BFS+heap+01背包)

18 篇文章 0 订阅
13 篇文章 0 订阅

Description

Download as PDF

Joko is taking part in a fire drill which is held by the Jakarta Fire Department to recruit new firemen. The drill is about rescuing volunteers (who act as unconscious people) trapped in a building in a limited time. The building has several floors, and the volunteers are scattered throughout the building. Each volunteer has points assigned to her. The fireman candidate should rescue volunteers through carrying them to the exit. The candidate will earn the assigned points for each volunteer he rescued.

Each floor of a building can be seen as a grid of cells. Each cell can be an obstacle, an empty space, a stair or an entry/exit point.

A candidate starts at the entry point which exists only at one single cell of the first floor of the building. The candidate can move to any adjacent non-obstacle cells (north, south, west or east) or climb up or down a stair in 1 second. The movement slows down to 2 seconds when the candidate carries a volunteer. When a candidate finds a volunteer, he may decide to rescue her or not, but if he decides to rescue her, he has to carry her back to the exit without stopping. He can only carry at most one volunteer at a time.

Joko has the floor plan of the test building. Help him plan his moves, so he can get the highest possible score.

Input

The first line of input contains an integer T(T$ \le$100) denoting the number of case. Each case has five integers L(1$ \le$L$ \le$10)H(1$ \le$H$ \le$100)W(1$ \le$W$ \le$100)N(1$ \le$N$ \le$100) and S(1$ \le$S$ \le$10, 000) denoting the number of floors, height and weight of each floor, the number of unconscious people, and the given time respectively.

The next L blocks describe the map of each floor from the 1st floor to the L-th floor respectively. Each floor consists of H lines each contains W characters. Characters that may appear in each floor are:

  • ``S" : The starting point, also serves as the exit point. There will be only one starting/exit point and it will appear in the first floor.
  • ``X" : Obstacle, cell that cannot be visited (wall, fire, etc.).
  • ``U" : Stair that connect to the upper floor. There will be a ``D" character at the same place in the upper level. This character will not appear in the highest level of the building.
  • ``D" : Stair that connect to the lower floor. There will be a ``U" character at the same place in the lower level. This character will not appear in the lowest level of the building.
  • ``." : Empty space, cell that can be visited.


The next N lines each contains four integers fi(1$ \le$fi$ \le$L)ri(1$ \le$ri$ \le$H)ci(1$ \le$ci$ \le$W)pi(1$ \le$pi$ \le$1, 000) denoting the location of each volunteer (floor, row, column) and the point assigned to this volunteer respectively. You can assume that each volunteer will be located in empty space and no two volunteer occupy the same location.

Output

For each case, output in a line a single integer the highest point that he can earn by rescuing unconscious people within the given time.

Sample Input

2 
3 3 5 3 55 
XXXXX 
X..UX 
XSXXX 
XXXXX 
XU.DX 
XXXXX 
XXXXX 
XD..X 
XXXXX 
1 2 3 10 
3 2 3 50 
3 2 4 60 
2 2 6 4 27 
...... 
S..U.. 
...... 
...D.. 
1 2 3 20 
1 2 5 50 
1 2 6 50 
2 1 1 90

Sample Output

110 
100


题意:一栋建筑物起火,里面有N个人需要救援,每个人对应一个分数,每救一个人就获得相应的分数,给出限定时间S,问在限定时间S内最多能获得多少分数。
思路:先用BFS求出救每个人需要用的时间,然后就是01背包解法。

AC代码:
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <vector>
#include <cstdlib>

using namespace std;
const int INF=1000000000;
struct node
{
    int f,r,c;
    int t;
    bool operator < (const node &a) const
    {
        return t>a.t;
    }
}start;
int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
char map[15][105][105];
int L,H,W,N,S,cnt;
int v[105],w[105];
int dp[10005];
int p[15][105][105];
int minmap[15][105][105];
bool judge(int r,int c)
{
    if(r>=1&&r<=H&&c>=1&&c<=W)
    return true;
    return false;
}
void BFS()
{
    priority_queue<node>Q;
    node cur,next;
    Q.push(start);
    for(int i=1;i<=L;i++)
    for(int j=1;j<=H;j++)
    for(int k=1;k<=W;k++)
    minmap[i][j][k]=INF;
    while(!Q.empty())
    {
        cur=Q.top();
        Q.pop();
        if(p[cur.f][cur.r][cur.c]!=-1)
        {
           w[cnt]=p[cur.f][cur.r][cur.c];
           v[cnt]=cur.t*3;
           cnt++;
           p[cur.f][cur.r][cur.c]=-1;
        }
        if(map[cur.f][cur.r][cur.c]=='U')
        {
           next.f=cur.f+1;
           next.r=cur.r;
           next.c=cur.c;
           next.t=cur.t+1;
           if(next.t<minmap[next.f][next.r][next.c])
           {
               minmap[next.f][next.r][next.c]=next.t;
               Q.push(next);
           }
        }
        else if(map[cur.f][cur.r][cur.c]=='D')
        {
            next.f=cur.f-1;
            next.r=cur.r;
            next.c=cur.c;
            next.t=cur.t+1;
            if(next.t<minmap[next.f][next.r][next.c])
            {
               minmap[next.f][next.r][next.c]=next.t;
               Q.push(next);
            }
        }
        for(int i=0;i<4;i++)
        {
            next=cur;
            next.r+=d[i][0];
            next.c+=d[i][1];
            if(!judge(next.r,next.c)) continue;
            if(map[next.f][next.r][next.c]=='X') continue;
            next.t++;
            if(next.t<minmap[next.f][next.r][next.c])
            {
               minmap[next.f][next.r][next.c]=next.t;
               Q.push(next);
            }
        }
    }
}
int main()
{
    int t,a,b,c,d;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d%d",&L,&H,&W,&N,&S);
        for(int i=1;i<=L;i++)
        for(int j=1;j<=H;j++)
        for(int k=1;k<=W;k++)
        {
        cin>>map[i][j][k];
        if(map[i][j][k]=='S')
        {
            start.f=i;
            start.r=j;
            start.c=k;
            start.t=0;
        }
        }
        memset(p,-1,sizeof(p));
        for(int i=0;i<N;i++)
        {
            scanf("%d%d%d%d",&a,&b,&c,&d);
            p[a][b][c]=d;
        }
        cnt=0;
        BFS();
        memset(dp,0,sizeof(dp));
        for(int i=0;i<cnt;i++)
        for(int j=S;j>=v[i];j--)
        dp[j]=max(dp[j],dp[j-v[i]]+w[i]);

        printf("%d\n",dp[S]);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值