题目链接: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;
}