UVALive - 5066 Fire Drill

2 篇文章 0 订阅

题目链接:https://cn.vjudge.net/problem/UVALive-5066#author=0

题意:有一L层,每层为一个H*W矩阵的楼,矩阵中有五种元素:X,.,U,D,S,分别代表障碍物,空地,向上楼梯,向下楼梯,起始点,现在有N个人的坐标信息及其救援价值(人都位于空地上),S秒的救援时间,移动一格花费一秒,带着人移动一个花费两秒,一次只能救一个人。问:在给定时间内能达到的最大救援价值是多少。

思路:bfs求出每个人的花费,01背包即可求解,详见代码

代码:

#include <iostream>
#include <queue>
#include <cstring>
#include <vector>

using namespace std;

struct node
{
	int l, y, x, step, w;
	node(int _l = 0,int _y = 0,int _x = 0,int _step = 0,int _w = 0) : l(_l), y(_y), x(_x), step(_step), w(_w){}
}man[110];

int T, F, N, M, n, m;
int dp[10010];
int Time[11][110][110], vis[11][110][110], Move[4][2] = {0,1,0,-1,1,0,-1,0};
char a[11][110][110];
queue <node> q;

bool check(int l,int y,int x)
{
	if(0 < y && y <= N && 0 < x && x <= M && a[l][y][x] != 'X' && !vis[l][y][x])
		return true;
	return false;
}

void bfs(int l,int y,int x)
{
	while(!q.empty()) q.pop();
	Time[l][y][x] = 0;
	vis[l][y][x] = 1;
	q.push(node(l,y,x,0,0));
	while(!q.empty()){
		node now = q.front(); q.pop();
		for(int i = 0; i < 4; ++i){
			if(!check(now.l,now.y+Move[i][0],now.x+Move[i][1]))
				continue;
			q.push(node(now.l,now.y+Move[i][0],now.x+Move[i][1],now.step+1,0));
			vis[now.l][now.y+Move[i][0]][now.x+Move[i][1]] = 1;
			Time[now.l][now.y+Move[i][0]][now.x+Move[i][1]] = now.step + 1;
		}
		if(a[now.l][now.y][now.x] == 'U'){
			if(check(now.l+1,now.y,now.x)){
				q.push(node(now.l+1,now.y,now.x,now.step+1,0));
				vis[now.l+1][now.y][now.x] = 1;
				Time[now.l+1][now.y][now.x] = now.step + 1;
			}
		}
		else if(a[now.l][now.y][now.x] == 'D'){
			if(check(now.l-1,now.y,now.x)){
				q.push(node(now.l-1,now.y,now.x,now.step+1,0));
				vis[now.l-1][now.y][now.x] = 1;
				Time[now.l-1][now.y][now.x] = now.step + 1;
			}
		}
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	cin>>T;
	while(T--){
		memset(Time, -1, sizeof Time);
		memset(dp, 0, sizeof dp);
		memset(vis, 0, sizeof vis);
		cin>>F>>N>>M>>n>>m;
		int sy, sx;
		for(int i = 1; i <= F; ++i)
			for(int j = 1; j <= N; ++j)
				for(int k = 1; k <= M; ++k){
					cin>>a[i][j][k];
					if(a[i][j][k] == 'S')
						sy = j, sx = k;
				}
		for(int i = 1; i <= n; ++i)
			cin>>man[i].l>>man[i].y>>man[i].x>>man[i].w;
		bfs(1,sy,sx);
		for(int i = 1; i <= n; ++i){
			int t = 3 * Time[man[i].l][man[i].y][man[i].x];
			if(t == -3) continue;	//人可能是不可达的
			for(int j = m; j >= t; --j){
				dp[j] = max(dp[j], dp[j-t] + man[i].w);
			}
		}
		cout<<dp[m]<<'\n';
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值