hdu1494 跑跑卡丁车(动态规划)
2024-08-30 06:18:41
Description
跑跑卡丁车是时下一款流行的网络休闲游戏,你可以在这虚拟的世界里体验驾驶的乐趣。这款游戏的特别之处是你可以通过漂移来获得一种
加速卡,用这种加速卡可以在有限的时间里提高你的速度。为了使问题简单化,我们假设一个赛道分为L段,并且给你通过每段赛道的普通耗时Ai和用加速卡的耗时Bi。加速卡的获得机制是:普通行驶的情况下,每通过1段赛道,可以获得20%的能量(N2O).能量集满后获得一个加速卡(同时能量清0).加速卡最多可以储存2个,也就是说当你有2个加速卡而能量再次集满,那么能量清零但得不到加速卡。一个加速卡只能维持一段赛道,游戏开始时没有加速卡。
加速卡,用这种加速卡可以在有限的时间里提高你的速度。为了使问题简单化,我们假设一个赛道分为L段,并且给你通过每段赛道的普通耗时Ai和用加速卡的耗时Bi。加速卡的获得机制是:普通行驶的情况下,每通过1段赛道,可以获得20%的能量(N2O).能量集满后获得一个加速卡(同时能量清0).加速卡最多可以储存2个,也就是说当你有2个加速卡而能量再次集满,那么能量清零但得不到加速卡。一个加速卡只能维持一段赛道,游戏开始时没有加速卡。
问题是,跑完n圈最少用时为多少?
Input
每组输入数据有3行,第一行有2个整数L(0<L<100),N(0<N<100)分别表示一圈赛道分为L段和有N圈赛道,接下来两行分别有L个整数Ai和Bi
(Ai > Bi).
(Ai > Bi).
Output
对于每组输入数据,输出一个整数表示最少的用时.
Sample Input
18 1
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
8 8 8 8 8 8 8 8 8 8 8 8 8 8 1 1 8 8
Sample Output
145 对于sample这组数据,你可以先在普通情况下行驶前14段,这时你有2个加速卡以及80%的能量(N2O).在第15和16段用掉2个加速卡,通过第
17段赛道后又可以得到一个加速卡,在第18段赛道使用. 这道本来很简单的dp,wa了一下午,刚开始的状态还是想的比较快的 dp[i][j][k]代表 第i段,有j个加速卡,现在的能量为k。然后就开始了无尽的wa之旅,wa点其实就三个。
首先我把数组给开小了....正好开了dp[10100][3][100],这个错误通过对拍,然后手推错误数据发现了,当时就想打自己,本来以为能ac了,结果还是wa,然后我一口气对拍了10w组b=1的数据,竟然没有错。然后又对拍了1000组 b=5时候的数据...竟然几乎一个对的都没有,仔细一看,原来是把n圈变成n*l段时,把l误用为了n,又想打自己,本来以为可以ac了,结果还是wa,继续对拍,b=5的时候 有3组数据,分别比正确答案多1 . 2 .3 这时候我确定肯定是状态转移出错了。刚开始的状态转移是这样的,当k==0时,情况可能是,在上一段能量到了80,这段攒了一个加速卡,还可能是,上一段有加速卡,并且用了且当时k==0,所以继续用加速卡,这段依然不增加能量,k==0.k>0时,情况可能是,如果有两张能量卡,那么说明是正常走了一段,如果小于两张,则可能是正常走了一段,或者用了一张加速卡。
经过仔细思考,我发现是因为我漏掉了一种我自认为不可能的情况,那就是有了两张卡,然后能量到了100,然后能量变为0,我本来想的是,卡不用白不用,让能量清0肯定不是最优解,但仔细想的话,如果你不想浪费这张新加速卡,就必须在到100的时候用掉原来的某张加速卡,这肯定是有各种反例的。所以这个题教会了我,动态规划的转移方程一定要写出所有符合条件的,不管你认为亏不亏,合不合理。就算亏他也会在转移中被更新,所以要写全。
#include<cstdio> #include<string.h> #include<algorithm> #define inf 0x3f3f3f3f const int maxn=; using namespace std; int l,n,ans; int dp[maxn+][][]; int a[maxn+]; int b[maxn+]; int main()
{
/* freopen("e://duipai//data.txt","r",stdin);
freopen("e://duipai//out2.txt","w",stdout);*/
while(scanf("%d%d",&l,&n)!=EOF){
ans=inf;
memset(dp,inf,sizeof(dp));
for(int i=;i<=l;i++){
scanf("%d",&a[i]);
for(int j=;j<n;j++){
a[j*l+i]=a[i];
}
}
for(int i=;i<=l;i++){
scanf("%d",&b[i]);
for(int j=;j<n;j++){
b[j*l+i]=b[i];
}
}
dp[][][]=;
for(int i=;i<;i++){
dp[i][][i*]=dp[i-][][(i-)*]+a[i];
}
for(int i=;i<=n*l;i++){
for(int j=;j<=;j++){
for(int k=;k<;k+=){
if(i<&&j>) continue;
if(!k){
if(j==){
dp[i][j][k]=min(dp[i][j][k],min(dp[i-][j-][]+a[i],dp[i-][j+][k]+b[i]));
} else if(j==){
dp[i][j][k]=min(dp[i][j][k],min(dp[i-][j-][]+a[i],dp[i-][j][]+a[i]));
} else if(!j) dp[i][j][k]=min(dp[i][j][k],dp[i-][j+][k]+b[i]);
} else if(k){
if(j==){
dp[i][j][k]=min(dp[i][j][k],dp[i-][j][k-]+a[i]);
}
if(j<){
dp[i][j][k]=min(dp[i][j][k],min(dp[i-][j][k-]+a[i],dp[i-][j+][k]+b[i]));
}
}
}
}
}
for(int i=;i<=;i++){
for(int j=;j<;j+=){
ans=min(ans,dp[n*l][i][j]);
}
}
printf("%d\n",ans);
}
return ;
}
最新文章
- 听说awk语言也可以编写脚本
- javascript中this指针探讨
- 再看erlang的socket部分基础
- Install mcrypt for php on Mac OSX 10.10 Yosemite for a Development Server
- Fluent Validation For .NET
- IEnumerable接口的扩展方法
- 正确安装 django-socketio
- 指针与数组、大小端之 printf(";%x,%x,%x\n";,*(a+1),ptr1[-1],*ptr2);
- Java 23种设计模式详尽分析与实例解析之三--行为型模式
- Swift - 浮点数转换成整数(四舍五入与直接截断)
- 201521123101 《Java程序设计》第11周学习总结
- 详谈Javascript类与继承
- 【bzoj4570 scoi2016】妖怪
- ReentrantReadWriteLock读写锁的使用1
- Quartz.NET 入门教程
- C++/C实现各种排序算法(持续更新)--冒泡排序,选择排序,归并排序
- mysql 让id字段 以1000 形式开头
- 洛谷P3384 【模板】树链剖分
- centos npm 安装后 command not found
- 如何在Power BI和Tableau之间进行选择?