• hdu2587(递推)


    目前做过的最纠结的一道递推题。

    情况比较多,比较复杂。。。

    这题最主要的还是要推出当m=2 时和m>2时,用什么方法最优。

    给个数据

    n=3,m=2   需要48

    n=3,m=3 需要81

    如果在纸上把这两种情况推出来,这题就容易找到递推。

    m=1,就是最基础的汉诺塔递推了。

    很O_O的汉诺塔

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 561    Accepted Submission(s): 67


    Problem Description
    O_O汉诺塔包含n种不同大小盘,每种大小m个; 要求每次仅移动一个盘,不允许一个较大的盘放在较小盘上。 并且要求最后排列所有相等大小盘按原来从上到下次序,并且只能按规定的方向搬运,如图(比如A直接搬运到C是不允许的!). 求已知n,m的情况下 从A搬运到C所有盘所用的最少次数。

     
    Input
    每行输入n和m两个整数 0<n<1000,0<m<100;
     
    Output
    每行输出对应解,为避免高精度将结果对20090308取模.
     
    Sample Input
    1 3 2 4
     
    Sample Output
    6 28
     
    Source
     
    //
    //  main.cpp
    //  hdu2587
    //
    //  Created by 陈加寿 on 16/3/17.
    //  Copyright © 2016年 chenhuan001. All rights reserved.
    //
    
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 1100
    #define MOD 20090308
    
    long long dp[N][2];
    
    //来一个统计,每个小块被搬多少次
    long long save[N][N][2];
    long long m;
    int tn;
    int g[N];
    
    long long dfs(int n,int flag)
    {
        if(dp[n][flag]!=-1) return dp[n][flag];
        if(flag == 1)
        {
            dp[n][flag] = (2*dfs(n-1,1)+2*m+dfs(n-1,0))%MOD;
            save[n][n][flag]=2;
            if(n== tn)
            {
                for(int i=1;i<=n-1;i++)
                {
                    save[n][i][flag]+=save[n-1][i][1]+save[n-1][i][0];
                    save[n][i][flag]%=2;
                }
            }
            else
            {
                for(int i=1;i<=n-1;i++)
                {
                    save[n][i][flag]+=2*save[n-1][i][1]+save[n-1][i][0];
                    save[n][i][flag]%=2;
                }
            }
        }
        else
        {
            dp[n][flag] = (2*dfs(n-1,1)+m)%MOD;
            save[n][n][flag] = 1;
            for(int i=1;i<=n-1;i++)
            {
                save[n][i][flag] += 2*save[n-1][i][1];
                save[n][i][flag]%=2;
            }
        }
        return dp[n][flag];
    }
    
    int main() {
        int n;
        while(cin>>n>>m)
        {
            tn = n;
            //来测试一种方法。!
            memset(save,0,sizeof(save));
            memset(g,0,sizeof(g));
            memset(dp,-1,sizeof(dp));
            dp[1][0] = m;
            save[1][1][0] = 1;
            dp[1][1] = 2*m;
            save[1][1][1] = 2;
            dfs(n,1);
            //对于n
            if(m>2)
            {
                if(n<=2)
                {
                    cout<<dp[n][1]<<endl;
                }
                else
                {
                    cout<<(dp[n][1]+2*(dp[n-2][1]+dp[n-2][0]))%MOD<<endl;//进行一次调整。
                }
            }
            else if(m==2)
            {
                //m == 2时
                if(n<=2)
                {
                    cout<<dp[n][1]<<endl;
                }
                else
                {
                    //int cnt=1;
                    //cout<<(dp[n][1]+2*(dp[n-2][1]+dp[n-2][0])-3*m*(n-2) )%MOD<<endl;//进行一次调整。
                    //各种不对。
                    long long tans=0;
                    for(int i=n;i>1;i--)
                    {
                        //把第i个块,从A放入C中
                        //第一步判断是否需要调整
                        if(g[i] == 1)
                        {
                            tans = (tans + dp[i-1][0] + dp[i-1][1])%MOD;//调整
                            for(int j=1;j<i;j++)
                            {
                                g[j] += save[i-1][j][0]+save[i-1][j][1];
                                g[j]%=2;
                            }
                        }
                        tans = (tans + dp[i-1][0] + dp[i-1][1]+2*m)%MOD;
                        for(int j=1;j<i;j++)
                        {
                            g[j] += save[i-1][j][0]+save[i-1][j][1];
                            g[j]%=2;
                        }
                    }
                    cout<<(tans+4)%MOD<<endl;//这样既然是对的,那么上面也是对的
                }
            }
            else// m == 1
            {
                cout<<dp[n][1]<<endl;
            }
    //        for(int i=1;i<=n-2;i++)
    //            save[n][i][1] += 2*save[n-2][i][0]+2*save[n-2][i][1];
    //
    //        for(int i=1;i<=n;i++)
    //            cout<<i<<" "<<save[n][i][1]<<endl;
        }
        return 0;
    }
  • 相关阅读:
    selenium 定制启动chrome的参数
    简单删除我的电脑里的wps云文档图标
    linux下设置git代理访问.
    关于要python爬虫你需要的一些网址和信息[待补充]
    在windows10 Linux (centos7)中安装go golang (够浪) 并测试运行
    ansible-cmdb 解析(ansible all -m setup )收集过来的信息并以html方式显示。
    使用python开发ansible自定义模块的简单案例
    关于openstack 网络相关的文章收集
    kubernets安装rabbitmq集群.
    centos7安装jenkins..
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5294665.html
Copyright © 2020-2023  润新知