zoukankan      html  css  js  c++  java
  • hdu1494 跑跑卡丁车(动态规划)

    Description

    跑跑卡丁车是时下一款流行的网络休闲游戏,你可以在这虚拟的世界里体验驾驶的乐趣。这款游戏的特别之处是你可以通过漂移来获得一种 
    加速卡,用这种加速卡可以在有限的时间里提高你的速度。为了使问题简单化,我们假设一个赛道分为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). 

    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的时候用掉原来的某张加速卡,这肯定是有各种反例的。所以这个题教会了我,动态规划的转移方程一定要写出所有符合条件的,不管你认为亏不亏,合不合理。就算亏他也会在转移中被更新,所以要写全。

     1 #include<cstdio>
     2 
     3 #include<string.h>
     4 
     5 #include<algorithm>
     6 
     7 #define inf 0x3f3f3f3f
     8 
     9 const int maxn=10000;
    10 
    11 using namespace std;
    12 
    13 int l,n,ans;
    14 
    15 int dp[maxn+10][5][120];
    16 
    17 int a[maxn+10];
    18 
    19 int b[maxn+10];
    20 
    21 int main()
    22 {
    23     /* freopen("e://duipai//data.txt","r",stdin);
    24       freopen("e://duipai//out2.txt","w",stdout);*/
    25     while(scanf("%d%d",&l,&n)!=EOF){
    26         ans=inf;
    27         memset(dp,inf,sizeof(dp));
    28         for(int i=1;i<=l;i++){
    29            scanf("%d",&a[i]);
    30            for(int j=1;j<n;j++){
    31                 a[j*l+i]=a[i];
    32            }
    33         }
    34         for(int i=1;i<=l;i++){
    35            scanf("%d",&b[i]);
    36            for(int j=1;j<n;j++){
    37                 b[j*l+i]=b[i];
    38            }
    39         }
    40         dp[0][0][0]=0;
    41         for(int i=1;i<5;i++){
    42                 dp[i][0][i*20]=dp[i-1][0][(i-1)*20]+a[i];
    43         }
    44         for(int i=5;i<=n*l;i++){
    45            for(int j=0;j<=2;j++){
    46                 for(int k=0;k<100;k+=20){
    47                       if(i<10&&j>1) continue;
    48                         if(!k){
    49                         if(j==1){
    50                         dp[i][j][k]=min(dp[i][j][k],min(dp[i-1][j-1][80]+a[i],dp[i-1][j+1][k]+b[i]));
    51                         } else if(j==2){
    52                           dp[i][j][k]=min(dp[i][j][k],min(dp[i-1][j-1][80]+a[i],dp[i-1][j][80]+a[i]));
    53                         } else if(!j) dp[i][j][k]=min(dp[i][j][k],dp[i-1][j+1][k]+b[i]);
    54                         } else if(k){
    55                         if(j==2){
    56                         dp[i][j][k]=min(dp[i][j][k],dp[i-1][j][k-20]+a[i]);
    57                         }
    58                         if(j<2){
    59                         dp[i][j][k]=min(dp[i][j][k],min(dp[i-1][j][k-20]+a[i],dp[i-1][j+1][k]+b[i]));
    60                         }
    61                         }
    62                }
    63             }
    64         }
    65         for(int i=0;i<=2;i++){
    66                 for(int j=0;j<100;j+=20){
    67                         ans=min(ans,dp[n*l][i][j]);
    68                 }
    69         }
    70         printf("%d
    ",ans);
    71     }
    72     return 0;
    73 }
    
    
  • 相关阅读:
    WCF 转 武胜
    NET(C#):GetHashCode不需要太复杂 转 武胜
    wcf KnownTypeAttribute 武胜
    memmove
    李开复谈创业失败十原因:经不住诱惑 直接山寨
    Linux使用Wine 安装source insight
    VM 中ubuntu下Eclipse ctrl+s 显示update conflict的问题
    ISO/OSI模型
    memset函数使用详解
    C语言中字符串的处理方式
  • 原文地址:https://www.cnblogs.com/GeniusYang/p/5742546.html
Copyright © 2011-2022 走看看