HDU - 1207 - 汉诺塔II(递推)

原题
  汉诺塔的变形,首先我们要知道如果要三根柱子的话,我们怎么来递推得到答案。如果是三根柱子的话,我们首先要把n-1个塔盘移动到第二根柱子上,然后再把最底下的塔盘放到第三根柱子上,
然后再把n-1个塔盘移动到第三根柱子上,所以递推式就是F(n) = F(n-1) x 2 + 1
  那么,如果再加一根柱子,情况又如何呢?我们参考上面的思路,首先,我们要先把i个塔盘移动到第二根柱子上,然后再把j个塔盘移动到第三根柱子上,最后剩下一个塔盘,把他移动到第四根柱子上,然后再把j个塔盘移动上去,最后再把i个塔盘移动到j+1个塔盘上面。注意,我们移动j个塔盘的时候,这些塔盘是不能移动到第二根柱子上的,因为第二根柱子上的塔盘都比他小,所以他的情况和三根柱子的情况类似,递推式是F(j+1) = F(j) x 2 + 1。然后我们移动i个塔盘的时候,我们所有的柱子都能用,所以我们所做的操作就是在所有柱子可用的把i个塔盘移动到第二根柱子然后再在所有柱子可用的情况下把他们全部移动到第四根柱子上,所以综合起来就是当i和j取某个值时,F(n) = F(i+j+1) = G(i) x 2 + U(j) x 2 + 1 = G(i) x 2 + U(j+1)。其中G(x)代表四根柱子可用的情况,U(x)代表三根柱子可用的情况,所以我们只要暴力求出i和j在所有可能的情况下的值然后取最小的函数值就能得到答案了

//https://www.cnblogs.com/shuitiangong/
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define endl '\n'
#define rtl rt<<1
#define rtr rt<<1|1
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define maxx(a, b) (a > b ? a : b)
#define minn(a, b) (a < b ? a : b)
#define zero(a) memset(a, 0, sizeof(a))
#define INF(a) memset(a, 0x3f, sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define _test printf("==================================================\n")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, ll> P2;
const double pi = acos(-1.0);
const double eps = 1e-7;
const ll MOD =  1000000007LL;
const int INF = 0x3f3f3f3f;
const int _NAN = -0x3f3f3f3f;
const double EULC = 0.5772156649015328;
const int NIL = -1;
template<typename T> void read(T &x){
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
const int maxn = 1e3+10;
ll h1[maxn], h2[maxn];
int main(void) {
    for (int i = 1; i<=12; ++i)
        h1[i] = h1[i-1]<<1|1; //求出三根柱子的情况
    for (int i = 1; i<=12; ++i) {
        h2[i] = INF;
        for (int j = 0; j<i; ++j)
            h2[i] = min(h2[i], h2[j]*2 + h1[i-j]); //求出在所有可能的i, j中的最小值
        printf("%lld\n", h2[i]);
    }
    return 0;
}
posted @ 2020-03-20 17:03  shuitiangong  阅读(220)  评论(0编辑  收藏  举报