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; }