http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=14911
题意:刘翔跨栏问题,初始有M能量,有N块区域需要跑,在第i可以使用3种模式:
1.Fast模式 通过第i个区域需要用T1[i]的时间,需要消耗F1[i]能量.
2.Normal模式 通过第i个区域需要用T2[i]的时间,不需要消耗能量.
3.Slow模式 通过第i个屈戌需要T3[i]的时间,能增加F2[i]能量,但是增加后的能量不能超过总能量M.
求通过N个区域的最短时间.
dp[i][j]表示 跑完前i个区域,剩下j体力的最短时间方案;
那么如果第i次选择 normal模式,则dp[i][j]=min(dp[i][j],dp[i-1][j]+t2[i]); 即从跑完前i-1段的体力到 跑完前i段的体力值不变,但是时间多了一个t2[i]
<span style="font-size:14px;">#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> #include <set> #include <vector> using namespace std; int i,j,k; int n,m; int min(int a,int b) {return a<b?a:b;} int t1[120],t2[120],t3[120],f1[120],f2[120]; int dp[120][120]; int main() { int t;cin>>t; while(t--) { scanf("%d%d",&n,&m); for (i=1;i<=n;i++) { scanf("%d%d%d%d%d",&t1[i],&t2[i],&t3[i],&f1[i],&f2[i]); } for (i=1;i<=n;i++) for (j=0;j<=m;j++) dp[i][j]=1000000; for(i=0;i<=m;i++) dp[0][i]=0; for (i=1;i<=n;i++) { for (j=0;j<=m;j++) { dp[i][j]=min(dp[i][j],dp[i-1][j]+t2[i]);//第i次选择中速跑,那么可由前i-1次跑完后剩下的j体力,推到跑完前i次的体力和min时间 if (j>=f1[i]) dp[i][j-f1[i]]=min(dp[i][j-f1[i]],dp[i-1][j]+t1[i]);//第i次选择快跑,可由前i-1次跑完剩下的j体力,推到跑完前i次后的体力为j-f1[i],和最短时间 dp[i][min(j+f2[i],m)]=min( dp[i][min(m,j+f2[i])],dp[i-1][j]+t3[i]);//第i次选择慢跑,可由前i-1次跑完剩下的j体力,推到跑完前i次后的体力为j+f2[i] //如果跑完第i次得到的能力超过了m,则看作m即可, } } int minn=dp[n][0]; for (i=0;i<=m;i++) { minn=min(minn,dp[n][i]); //在剩下0-m点体力的情况,取最短的时间的方案 } printf("%d\n",minn); } return 0; }</span>