http://acm.hdu.edu.cn/showproblem.php?pid=1494
这题是道简单dp。
输入跑道段数l,和圈数n,接着是每段跑道不用加速器时间a[],再接着是用了加速器所需时间b[]。
1.用了加速卡的那段不会得到能量。
2.这里可以看成是n*l段长度的路程,转移量为能量槽数,最大为14.
3.注意能量为10的情况除了可以由能量为9(常规不用加速卡)的情况得到,
还可以由能量为14(不用加速卡,下一步获得能量为15,清空能量槽,变为10) 的情况得到。
具体看代码:
<span style="font-size:18px;">#include <stdio.h>
#include <iostream>
#define INF 0xffffff
#define MAX 10000
using namespace std;
int dp[MAX+5][20]; //dp[i][j]:到第i段跑道,能量为j时最短时间。
int a[MAX+5],b[MAX+5];
void init()
{
int i,j;
for(i=0;i<=MAX;i++) //注意有些情况事不可能出现的,比如:在第一段跑道有2个能量
for(j=0;j<15;j++) //所以要全部初始化为∞
dp[i][j]=INF;
dp[0][0]=0; //在起点能量为0
}
inline int fmin(int a,int b)
{
return a<b?a:b;
}
int main()
{
int l,n,i,j;
while(scanf("%d %d",&l,&n)!=EOF)
{
init();
for(i=1;i<=l;i++) //把n圈化为1全n*l段
scanf("%d",&a[i]);
for(i=1;i<n;i++)
for(j=1;j<=l;j++)
a[i*l+j]=a[j];
for(i=1;i<=l;i++)
scanf("%d",&b[i]);
for(i=1;i<n;i++)
for(j=1;j<=l;j++)
b[i*l+j]=b[j];
for(i=1;i<=l*n;i++) //dp[i][j]:在第i阶段还有j格能量槽的时间
{
for(j=0;j<15;j++)
{
if(j!=0)
dp[i][j]=fmin(dp[i-1][j-1]+a[i],dp[i][j]);//不用加速卡
if(j<=9)
dp[i][j]=fmin(dp[i-1][j+5]+b[i],dp[i][j]);//用了加速卡
if(j==10)
dp[i][10]=fmin(dp[i][j],dp[i-1][14]+a[i]);<span style="white-space:pre"> </span>//就是在这坑了,题意呀!!
}
}
int min=INF;
/*
for(i=1;i<=l*n;i++)
{
for(j=0;j<=14;j++)
{
if(dp[i][j]>1000)
printf("* ");
else
printf("%4d",dp[i][j]);
}
printf("\n");
}
*/
for(i=0;i<15;i++)
min=fmin(min,dp[l*n][i]);
printf("%d\n",min);
}
return 0;
}</span>