ZOJ - 2972-Hurdles of 110m-DP

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]

那么如果第i次选择 fast模式,则dp[i][j-f1[i]]=min(dp[i][j-f1[i]],dp[i-1][j]+t1[i]);    即从跑完前i-1段的体力为j,到 跑完前i段的体力值变为 j-f1[i],时间多了一个t1[i];

那么如果第i次选择 fast模式,则
  dp[i][min(j+f2[i],m)]=min( dp[i][min(m,j+f2[i])],dp[i-1][j]+t3[i]);   即从跑完前i-1段的体力为j,到 跑完前i段的体力值变为 j+f2[i],时间多了一个t3[i];

并且 如果最后 体力值增加到超过了m,就需要 看作m;




 





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


那么如果第i次选择 fast模式,则dp[i][j-f1[i]]=min(dp[i][j-f1[i]],dp[i-1][j]+t1[i]);    即从跑完前i-1段的体力为j,到 跑完前i段的体力值变为 j-f1[i],时间多了一个t1 [i];

你可能感兴趣的:(ZOJ - 2972-Hurdles of 110m-DP)