题意:牛要建立长为n的云霄飞车,可以有m个事件点,每个事件设计4个变量,即从a点开始,长为b,给牛f的开心值,要花费c元。牛总共有b元,它们想从0开始,一直经历事件点到最后,使得开心值最大,求此值。

题解:对每个事件点建立一条边,同时用dp[i][j]代表第i个点话费了j的钱所能得到的最大开心值,然后用类似dijiskra的算法,从0到n-1开始松弛,再从dp[n][..]中选一个最大的即可。

View Code
 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 }