UVALive 5066 Fire Drill --BFS+DP

题意:有一个三维的地图,有n个人被困住,现在消防队员只能从1楼的一个入口进入,营救被困者,每一个被困者有一个价值,当消防队员找到一个被困者之后,他可以营救或者见死不救,如果救的话,他必须马上将其背到入口处,不得停下,不得同时救多个人,而且回去的时间一步要做两步走,即时间增加一倍。求在给定时间S内,能救到的人的最大价值总和。

解法:bfs一遍记录每个点离起点的最短距离,那么救这个人的花费就是3*dis,然后已经知道救这个人的价值,那么最后求一个01背包即可。

要注意一个人都救不到的地方,我开始将dis都初始化为1000000007,这样的话如果走不到的话,花费就变成3*dis爆int了。悲剧。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#define Mod 10000007
using namespace std;
#define N 50107

char mp[15][125][125];
int dis[15][125][125];
int dp[10006];
int T[114],P[114],L,H,W;
int dx[7] = {0,0,0,0,  1,  -1};
int dy[7] = {0,1,-1,0, 0,  0,};
int dz[7] = {1,0,0,-1, 0,  0,};
struct node {
    int l,h,w,sec;
    node(int _x,int _y,int _z,int _sec):l(_x),h(_y),w(_z),sec(_sec){}
    node(){}
}vol[135],S;

bool OK(int x,int y,int z) {
    if(x >= 0 && x < L && y >= 0 && y < H && z >= 0 && z < W)
        return true;
    return false;
}

void bfs(node S) {
    queue<node> q;
    while(!q.empty()) q.pop();
    int i,j,k;
    for(i=0;i<L;i++)
        for(j=0;j<H;j++)
            for(k=0;k<W;k++)
                dis[i][j][k] = Mod;
    int x = S.l, y = S.h, z = S.w;
    dis[x][y][z] = 0;
    q.push(S);
    while(!q.empty()) {
        node now = q.front();
        q.pop();
        int l = now.l, h = now.h, w = now.w, sec = now.sec;
        if(mp[l][h][w] == ‘U‘) {
            for(k=0;k<5;k++) {
                int nx = l + dx[k];
                int ny = h + dy[k];
                int nz = w + dz[k];
                if(!OK(nx,ny,nz)) continue;
                if(mp[nx][ny][nz] != ‘X‘) {
                    if(sec+1 < dis[nx][ny][nz]) {
                        dis[nx][ny][nz] = sec+1;
                        node tmp = node(nx,ny,nz,sec+1);
                        q.push(tmp);
                    }
                }
            }
        }
        else if(mp[l][h][w] == ‘D‘) {
            for(k=0;k<6;k++) {
                if(k == 4) continue;
                int nx = l + dx[k];
                int ny = h + dy[k];
                int nz = w + dz[k];
                if(!OK(nx,ny,nz)) continue;
                if(mp[nx][ny][nz] != ‘X‘) {
                    if(sec+1 < dis[nx][ny][nz]) {
                        dis[nx][ny][nz] = sec+1;
                        node tmp = node(nx,ny,nz,sec+1);
                        q.push(tmp);
                    }
                }
            }
        }
        else {
            for(k=0;k<4;k++) {
                int nx = l + dx[k];
                int ny = h + dy[k];
                int nz = w + dz[k];
                if(!OK(nx,ny,nz)) continue;
                if(mp[nx][ny][nz] != ‘X‘) {
                    if(sec+1 < dis[nx][ny][nz]) {
                        dis[nx][ny][nz] = sec+1;
                        node tmp = node(nx,ny,nz,sec+1);
                        q.push(tmp);
                    }
                }
            }
        }
    }
}

int main()
{
    int t,n,STime,i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d%d",&L,&H,&W,&n,&STime);
        for(i=0;i<L;i++) {
            for(j=0;j<H;j++) {
                scanf("%s",mp[i][j]);
                for(k=0;k<W;k++)
                    if(mp[i][j][k] == ‘S‘)
                        S = node(i,j,k,0);
            }
        }
        for(i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&vol[i].l,&vol[i].h,&vol[i].w,&P[i]);
            vol[i].l--,vol[i].h--,vol[i].w--;
        }
        bfs(S);
        for(i=1;i<=n;i++)
            T[i] = 3*dis[vol[i].l][vol[i].h][vol[i].w];
        memset(dp,0,sizeof(dp));
        for(i=1;i<=n;i++) {
            for(j=STime;j>=0;j--) {
                if(j >= T[i])
                    dp[j] = max(dp[j],dp[j-T[i]]+P[i]);
            }
        }
        int Maxi = 0;
        for(i=0;i<=STime;i++)
            Maxi = max(Maxi,dp[i]);
        printf("%d\n",Maxi);
    }
    return 0;
}

时间: 2024-10-12 14:49:00

UVALive 5066 Fire Drill --BFS+DP的相关文章

UVALive 5066 Fire Drill BFS+背包

H - Fire Drill Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVALive 5066 Description Joko is taking part in a fire drill which is held by the Jakarta Fire Department to recruit new firemen. The drill i

HDU 1072 Nightmare( 身上带有定时炸弹的他能否在炸弹爆炸之前离开—— BFS+DP思想)

Nightmare Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description Ignatius had a nightmare last night. He found himself in a labyrinth with a time bomb on him. The labyrinth has an exit, Ignatius should get out of the

ZOJ 3596Digit Number(BFS+DP)

一道比较不错的BFS+DP题目 题意很简单,就是问一个刚好包含m(m<=10)个不同数字的n的最小倍数. 很明显如果直接枚举每一位是什么这样的话显然复杂度是没有上限的,所以需要找到一个状态表示方法: 令F[i][j] 表示已经用了 i (二进制压位表示)用了 i 这些数字,且余数j为的状态,枚举时直接枚举当前位,那么答案明显就是F[m][0] 我这里将状态i, j存在了一维空间里,即 i * 1000 + j表示,实际上用一个结构体存队列里的点,用二维数组标记状态也是可行的. 1 #includ

ACM/ICPC 之 最短路-Floyd+SPFA(BFS)+DP(ZOJ1232)

这是一道非常好的题目,融合了很多知识点. ZOJ1232-Adventrue of Super Mario 这一题折磨我挺长时间的,不过最后做出来非常开心啊,哇咔咔咔 题意就不累述了,注释有写,难点在于状态转移方程的确立和SPFA的过程 1 //最短路:Floyd+SPFA(BFS)+DP 2 //Time:20Ms Memory:336K 3 //题目很好,数据较弱,网上部分代码有些问题却能够A掉 4 //题意:超级马里奥要从A+B处背着公主以最短路程到达1处,其中1-A是村庄,剩下的是城堡

【2019.8.14 慈溪模拟赛 T1】我不是!我没有!别瞎说啊!(notme)(BFS+DP)

\(IDA^*\) 说实话,这道题我一开始没想出正解,于是写了一个\(IDA^*\)... 但神奇的是,这个\(IDA^*\)居然连字符串长度分别为\(2500,4000\)的数据都跑得飞快,不过数据发下来之后我测了一下只有45分. 就在不断优化\(IDA^*\)的过程中,我突然就想出了正解的做法,看来以后遇事不决先暴力. \(DP\)求解第一个询问 考虑一个\(DP\),我们设\(f_{i,j}\)表示当前在第一个字符串中是第\(i\)位,第二个字符串中是第\(j\)位的最小步数. 若记录\(

UVALive 4025 Color Squares(BFS)

题目链接:UVALive 4025 Color Squares 按题意要求涂色,求达到w分的最少步数. //yy:哇,看别人存下整个棋盘的状态来做,我什么都不想说了,不知道下午自己写了些什么东西,训练结束补的.. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #define CLR(a, b) memset((a),(b),sizeof

(简单) UVA 11624 Fire! ,BFS。

Description Joe works in a maze. Unfortunately, portions of the maze have caught on fire, and the owner of the maze neglected to create a fire escape plan. Help Joe escape the maze. Given Joe's location in the maze and which squares of the maze are o

hdu 3247 Resource Archiver(AC自动机+BFS+DP)

题目链接:hdu 3247 Resource Archiver 题目大意:给定N个需要包含的串,M个不能包含的串,问说满足的最短字符串长度. 解题思路:直接对所有串建立AC自动机,不能满足的串用同一种标记即可.然后处理出所有属于需要包含串的单词节 点,用BFS处理出两两之间的距离,并且过程中是不能经过禁止节点.这样做的原因是节点的个数很多,如果对所有的 节点进行dp的话空间都不够.剩下的就是dp了. #include <cstdio> #include <cstring> #inc

HDU3247 Resource Archiver(AC自动机+BFS+DP)

题目,求最短的包含所有n个DNA片段且不包含任何一个病毒片段的序列. 容易用所有DNA片段和病毒片段建一个AC自动机,构造fail时处理一下各个结点后缀是DNA或者病毒的情况,然后dp[S][u]表示包含DNA片段的集合是S的且后缀状态是自动机第u个结点的最短序列长度,然后顺着AC自动机避开病毒串转移. 不过构建的AC自动机结点上限60000左右,集合有1024个状态,这样内存开不下.看了题解,原来不必要考虑自动机所有结点—— dp[S][u]表示包含DNA片段集合是S且后缀是第u个DNA片段的