ACM/ICPC Live Archive 5066
問題概要
三次元のマップが与えられます.
- 'S' : 出入り口
- 'X' : 壁
- '.' : 歩ける場所
- 'U' : 上の階へ上がれる場所
- 'D' : 下の階へ下がれる場所
建物の中に, 助けを求めている人がN人います. それぞれ, 助けるともらえるポイントpiがついています.
ある消防士がいて, なるべく点数が高くなるように救出を行いたいと思っています.
S秒の時間制限があるとき, 救出の最高点数はいくらでしょう.
消防士は, 歩くたびに1秒消費し, 人を背負っている場合は2秒消費します.
人は, 一度に一人しか背負うことができず, 救出したい場合は一旦入り口まで運ぶ必要があります.
プログラム
#include <iostream> #include <queue> #include <cstdio> #include <cstring> using namespace std; #define REP(i,n,m) for(int i=n;i<m;i++) #define rep(i,n) REP(i,0,n) class State{ public: int x,y,z; State(){} State(int _x,int _y,int _z){x=_x;y=_y;z=_z;} }; int f,h,w,n,s; int sx,sy; int weight[102],price[102]; int dist[12][102][102]; int dp[102][10002]; char t[12][102][102]; int dx[] = {-1,1,0,0}; int dy[] = {0,0,1,-1}; void mkDist(){ queue<State> open; open.push(State(sx,sy,0)); memset(dist,-1,sizeof(dist)); dist[0][sy][sx] = 0; while(!open.empty()){ State st = open.front(); open.pop(); rep(i,4){ int nx = st.x + dx[i]; int ny = st.y + dy[i]; if(nx>=0 && w>nx && ny>=0 && h>ny && t[st.z][ny][nx]!='X' && dist[st.z][ny][nx]==-1){ dist[st.z][ny][nx] = dist[st.z][st.y][st.x] + 1; open.push(State(nx,ny,st.z)); } } if(t[st.z][st.y][st.x]=='U' && dist[st.z+1][st.y][st.x]==-1){ dist[st.z+1][st.y][st.x] = dist[st.z][st.y][st.x] + 1; open.push(State(st.x,st.y,st.z+1)); } else if(t[st.z][st.y][st.x]=='D' && dist[st.z-1][st.y][st.x]==-1){ dist[st.z-1][st.y][st.x] = dist[st.z][st.y][st.x] + 1; open.push(State(st.x,st.y,st.z-1)); } } } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d%d%d%d",&f,&h,&w,&n,&s); sx = sy = -1; rep(i,f){ rep(j,h){ scanf("%s",t[i][j]); if(sx!=-1) continue; rep(k,w){ if(t[i][j][k] == 'S'){ sx = k; sy = j; break; } } } } mkDist(); rep(i,n){ int x,y,z; scanf("%d%d%d%d",&z,&y,&x,&price[i]); weight[i] = dist[z-1][y-1][x-1] * 3; } memset(dp,-1,sizeof(dp)); dp[0][0] = 0; rep(i,n){ rep(j,s+1){ if(dp[i][j] != -1){ if(weight[i] >= 0){ int nw = j + weight[i]; int np = dp[i][j] + price[i]; if(nw <= s && (dp[i+1][nw] == -1 || np > dp[i+1][nw])){ dp[i+1][nw] = np; } } if(dp[i+1][j] == -1 || dp[i][j] > dp[i+1][j]){ dp[i+1][j] = dp[i][j]; } } } } int ans = 0; rep(i,s+1){ if(ans < dp[n][i]){ ans = dp[n][i]; } } printf("%d\n",ans); } }