zoukankan      html  css  js  c++  java
  • ACMICPC Live Archive 2031 Dance Dance Revolution

    动态规划

    黑书的例题,老题了,2000年的国赛题,题意看黑书吧,太长了。。。比较典型的按阶段性决策,整个dp还是不难想的,1A

    分析在代码中

    /*
    按时间决策的DP,或者说按阶段性决策
    当前要跳的格子出现了,那么怎么跳其实只有两种选择,用左脚去踩或者右脚去踩
    所以要枚举前一个格子结束的时候,左右脚在什么地方,如果用左脚踩会产生多少花费,用右脚踩会产生多少花费
    dp[i][l][r]表示踩完第i次,左脚在l这个格子上,右脚在r这个格子上的最小花费
    那么最终要找的答案在dp[n][l][r]中,所以要扫描一次dp[n]找到最大值
    由题目的性质就知道可以使用滚动数组,而且题目也没提到序列的长度,所以用滚动数组也更为保险
    */
    #include <cstdio>
    #include <cstring>
    #define min(a,b) a<b?a:b
    #define INF 0x3f3f3f3f
    
    long long dp[2][5][5]; //滚动数组,dp[0]上一次,dp[1]这一次
    
    int cal(int x ,int s)
    {
        int cost;
        if(x==0) cost=2; //从中心到任何位置都是2
        else if(x==s) cost=1; //原地踩为1
        else if((x==1 && s==3)||(x==3 && s==1)||(x==2 && s==4)||(x==4 && s==2))
            cost=4; //移动到对面
        else //相邻的移动
            cost=3;
        return cost;
    }
    
    int main()
    {
        int s;
        while(scanf("%d",&s)!=EOF && s)
        {
            memset(dp,0x3f,sizeof(dp));
            //一开始两个脚都在中心
            dp[0][s][0]=2; //用左脚去踩第一个
            dp[0][0][s]=2; //用右脚去踩第一个
            while(scanf("%d",&s) && s)
            {
                for(int l=0; l<5; l++) //初始化
                    for(int r=0; r<5; r++)
                        dp[1][l][r]=INF;
                //用左脚去踩,那么右脚和之前的位置是相同的
                //右脚不动,那么先枚举右脚的位置,但是右脚不能站在当前要踩的位置
                //再枚举左脚之前站的位置,左脚之前站的位置与右脚位置也不能相同
                for(int r=0; r<5; r++)
                    if(r!=s) //枚举右脚,但是右脚不能与当前位置相同
                        for(int l=0; l<5; l++)
                            if(l!=r) //左脚和右脚位置不相同
                            {
                                int cost=cal(l,s); //计算这样移动的花费
                                dp[1][s][r] = min(dp[1][s][r] , dp[0][l][r]+cost);
                            }
                //同样地用右脚去踩,那么左脚和之间的位置是相同的
                //左脚不动,那么先枚举左脚的位置,但是左脚不能与当前要踩的格子相同
                //再枚举右脚之前站的位置,但是右脚的位置不能和左脚位置相同
                for(int l=0; l<5; l++) //先枚举左脚
                    if(l!=s)
                        for(int r=0; r<5; r++) //再枚举右脚
                            if(r!=l) //左右脚位置不同
                            {
                                int cost=cal(r,s);
                                dp[1][l][s] = min(dp[1][l][s] , dp[0][l][r]+cost);
                            }
    
                //滚动数组,复制过去
                for(int l=0; l<5; l++)
                    for(int r=0; r<5; r++)
                        dp[0][l][r]=dp[1][l][r];
            }
    
            long long ans=INF;
            for(int l=0; l<5; l++)
                for(int r=0; r<5; r++)
                    ans = min(ans,dp[0][l][r]);
            printf("%lld\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    22_selenium_使用cookie直接登录
    21_无头模式
    自动化测试-设计模式-介绍
    Doorls
    pytest-Allure报告
    pytest-架构1
    pytest-第一次学习梳理
    web测试
    测试-工时评估
    封装pyuic5转换ui文件的脚本
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2977849.html
Copyright © 2011-2022 走看看