题目链接:https://cn.vjudge.net/problem/ZOJ-2972
题目大意
刘翔跨栏,一共有n个栏,跨每个栏的时候都有三种方式,刘翔初始体力为m。
1、快速通过,花费时间为t1,消耗体力f1。
2、正常速度,花费时间为t2,不消耗体力。
3、慢速通过,花费时间为t3,恢复体力f2,恢复上限为m。
问:跨完n个栏需要的最少时间(过程中体力不能小于0)。
分析
dp[i][j]表示通过 i 个栏,剩余体力为 j 时,花费的最小时间。
当快速通过时,dp[i][j-f1] = min(dp[i][j-f1], dp[i-1][j]+t1)。
正常速度通过时,dp[i][j] = min(dp[i][j], dp[i-1][j]+t2)。
慢速通过时,dp[i][sum] = min(dp[i][sum], dp[i-1][j]+t3)。
代码
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
#define inf 0x3f3f3f3f
int dp[150][150];
int main()
{
int t,n,m,t1,t2,t3,f1,f2;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(dp,inf,sizeof dp);
dp[0][m]=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d%d",&t1,&t2,&t3,&f1,&f2);
for(int j=m;j>=0;j--)
{
dp[i][j] = min(dp[i][j], dp[i-1][j]+t2);
if(j>=f1)
dp[i][j-f1] = min(dp[i][j-f1], dp[i-1][j]+t1);
int sum = j+f2;
if(sum>m) sum = m;
dp[i][sum] = min(dp[i][sum], dp[i-1][j]+t3);
}
}
int ans = inf;
for(int i=0;i<=m;i++)//通过n个栏,在所有剩余体力里面找花费时间最小的
ans = min(ans, dp[n][i]);
printf("%d\n",ans);
}
return 0;
}