2013成都区域赛的题目
题意:
某人从1号房子走到n号房子去拜访朋友,他经过其他房子的时候可以买卖盐。求最后在时间T内到朋友家最多能赚多少钱。
还有一些规则:
1.1号房和n号房不能买卖盐,一开始有R元,最多能携带B袋盐。
2.经过每条路需要花费时间和金钱,每个房子只能买卖一袋盐,交易不需要时间。
3.不同房子盐的价格不一样,而且还存在K个平行宇宙,每个平行宇宙盐的价格也不一样。
4.自己和朋友在0宇宙,不能在别的宇宙到达1号房子和n号房子。
5.宇宙穿梭需要花费1分钟的时间,从i宇宙到(i+1)%K宇宙。
6.一旦到达n号房子,旅途立即结束。
思路:
dp[T][K][B][N] 四维分别表示时间,在哪个宇宙,带了多少袋盐,在哪号房子, 此时获得的最多金钱。
转移写清楚即可。
我是分三种交易情况转移(不交易,买,卖),每种情况交易完后再进行移动的转移(走到其他房子或者穿梭宇宙)。
code:
#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
#define N 100010
#define ll long long
#define ALL(x) x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
#define bit(st,i) ((1ll<<i)&st)
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int MOD =1000003;
const double EPS=1e-7;
int n,m,B,K,R,T;
int dp[201][5][5][101];
int p[5][101];
struct Edge{
int v,time,cost,next;
}e[256];
int eid,head[128];
void insert(int from,int to,int time,int cost){
e[eid].v=to;
e[eid].time=time;
e[eid].cost=cost;
e[eid].next=head[from];
head[from]=eid++;
}
void init(){
CLR(head,-1);
eid=0;
}
void move(int t,int k,int b,int u,int val){
for(int i=head[u];~i;i=e[i].next){
int v=e[i].v;
int _t=t+e[i].time;
if(_t<=T && val-e[i].cost>=0)
dp[_t][k][b][v]=max(dp[_t][k][b][v],val-e[i].cost);
}
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 re,Case=1;
scanf("%d",&re);
while(re--){
scanf("%d%d%d%d%d%d",&n,&m,&B,&K,&R,&T);
for(int i=0;i<K;i++)
for(int j=1;j<=n;j++)
scanf("%d",&p[i][j]);
init();
while(m--){
int x,y,t,c;
scanf("%d%d%d%d",&x,&y,&t,&c);
insert(x,y,t,c);
}
CLR(dp,-1);
dp[0][0][0][1]=R;
for(int t=0;t<=T;t++){
for(int k=0;k<K;k++){
for(int b=0;b<=B;b++){
for(int i=1;i<n;i++){
if(dp[t][k][b][i]==-1) continue;
move(t,k,b,i,dp[t][k][b][i]); //no trade
if(b<B && i!=1) move(t,k,b+1,i,dp[t][k][b][i]-p[k][i]); //sell a salt
if(b && i!=1) move(t,k,b-1,i,dp[t][k][b][i]+p[k][i]); //buy a salt
}
}
}
}
printf("Case #%d: ",Case++);
int ans=-1;
for(int t=0;t<=T;t++)
ans=max(ans,dp[t][0][0][n]);
if(ans==-1) puts("Forever Alone");
else printf("%d\n",ans);
}
return 0;
}