题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4784
题意:一个人要到他男朋友家,他最初有R元以及T分钟的时间来赶到他男朋友家。有N个房子M条道路,每条道路有需要消耗的时间以及过路费,同时还要顺路做食盐生意,起初身上没有食盐,最多带B袋盐,每到达一个地方有三种操作可以选择:1.售出一袋食盐;2:购买一袋食盐;3:什么都不做。然后你以为结束了?不!它还存在平行宇宙,在一个城市可以选择穿越平行宇宙到达另一个宇宙的这个城市,不同宇宙的食盐价格不同但是过路费和道路需要的时间是相同的,而且由于他是穿越党,他不能在别的宇宙回到自己家或者男朋友家,求最后能否到达他男朋友家以及最多能有多少钱。
解法:BFS或者直接DP。我是直接DP的,考虑DP[t][i][j][k]代表当前时间为t,在第i个宇宙,背包容量为j,当前house为k最多有多少钱,然后按照题意去转移即可,也可以把这个过程用BFS来写,道理都一样。
#include <bits/stdc++.h>
using namespace std;
int N,M,B,K,R,T;
const int maxn = 110;
const int maxm = 210;
struct node{
int time,val,to,next;
node(){}
}E[maxm];
int dp[210][10][10][110];
int p[10][210];
int head[maxn],edgecnt;
void init(){
edgecnt=0;
memset(head,-1,sizeof(head));
}
void add(int u, int v, int time, int val){
E[edgecnt].time = time;
E[edgecnt].val = val;
E[edgecnt].to = v;
E[edgecnt].next = head[u];
head[u] = edgecnt++;
}
void solve(int t, int k, int b, int u, int val){
for(int i=head[u]; ~i; i=E[i].next){
int v = E[i].to;
int tt = t + E[i].time;
int w = E[i].val;
if(tt <= T && val >= w){
dp[tt][k][b][v] = max(dp[tt][k][b][v], val-w);
}
}
if(u!=1&&t+1<=T){
dp[t+1][(k+1)%K][b][u] = max(dp[t+1][(k+1)%K][b][u], val);
}
}
int main(){
int T_T, ks = 0;
scanf("%d", &T_T);
while(T_T--){
init();
scanf("%d %d %d %d %d %d", &N,&M,&B,&K,&R,&T);
memset(p, 0, sizeof(p));
for(int i=0; i<K; i++)
for(int j=1; j<=N; j++)
scanf("%d", &p[i][j]);
for(int i=1; i<=M; i++){
int u,v,t,w;
scanf("%d %d %d %d", &u,&v,&t,&w);
add(u, v, t, w);
}
//dp
memset(dp, -1, sizeof(dp));
dp[0][0][0][1] = R;
for(int i=0; i<=T; i++){
for(int j=0; j<K; j++){
for(int x=0; x<=B; x++){
for(int u=1; u<N; u++){
if(dp[i][j][x][u] == -1) continue;
solve(i,j,x,u,dp[i][j][x][u]);
if(u>1&&x>0) solve(i,j,x-1,u,dp[i][j][x][u]+p[j][u]);
if(u>1&&x<B) solve(i,j,x+1,u,dp[i][j][x][u]-p[j][u]);
}
}
}
}
int ans = -1;
for(int i=0; i<=T; i++){
ans = max(ans, dp[i][0][0][N]);
}
if(ans == -1){
printf("Case #%d: Forever Alone\n", ++ks);
}else{
printf("Case #%d: %d\n", ++ks, ans);
}
}
return 0;
}