题意:牛要建立长为n的云霄飞车,可以有m个事件点,每个事件设计4个变量,即从a点开始,长为b,给牛f的开心值,要花费c元。牛总共有b元,它们想从0开始,一直经历事件点到最后,使得开心值最大,求此值。
题解:对每个事件点建立一条边,同时用dp[i][j]代表第i个点话费了j的钱所能得到的最大开心值,然后用类似dijiskra的算法,从0到n-1开始松弛,再从dp[n][..]中选一个最大的即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int dp[1005][1005]; 6 int head[1005],nhead[1005],nc,dc; 7 struct Edge 8 { 9 int to,cost,fun,next; 10 }edge[3000000]; 11 struct Data 12 { 13 int to,cost,next; 14 }data[3000000]; 15 void add(int a,int b,int f,int c) 16 { 17 edge[nc].to=b;edge[nc].next=head[a];edge[nc].cost=c;edge[nc].fun=f;head[a]=nc++; 18 } 19 void add(int a,int b,int c) 20 { 21 data[dc].to=b;data[dc].next=nhead[a];data[dc].cost=c;nhead[a]=dc++; 22 } 23 int n,b; 24 int solve() 25 { 26 dp[0][0]=0; 27 add(0,0,0); 28 for(int i=0;i<n;i++) 29 { 30 for(int j=head[i];j!=-1;j=edge[j].next) 31 { 32 int t=edge[j].to,f=edge[j].fun,c=edge[j].cost; 33 for(int k=nhead[i];k!=-1;k=data[k].next) 34 { 35 int tt=data[k].to,cc=data[k].cost; 36 if(dp[i][tt]!=cc||tt+c>b) 37 continue; 38 if(dp[t][tt+c]<dp[i][tt]+f) 39 { 40 dp[t][tt+c]=cc+f; 41 add(t,tt+c,cc+f); 42 } 43 } 44 } 45 } 46 int ans=-1; 47 for(int i=nhead[n];i!=-1;i=data[i].next) 48 { 49 ans=max(ans,data[i].cost); 50 } 51 return ans; 52 } 53 int main() 54 { 55 int m; 56 while(scanf("%d%d%d",&n,&m,&b)!=EOF) 57 { 58 memset(head,-1,sizeof(head)); 59 memset(nhead,-1,sizeof(nhead)); 60 nc=dc=0; 61 memset(dp,-1,sizeof(dp)); 62 for(int i=0;i<m;i++) 63 { 64 int a,b,c,f; 65 scanf("%d%d%d%d",&a,&b,&f,&c); 66 b+=a; 67 add(a,b,f,c); 68 } 69 printf("%d\n",solve()); 70 } 71 return 0; 72 }