dp超时的另外一种优化,找规律(四塔问题)

四塔问题

“汉诺塔”,是一个众所周知的古老游戏。现在我们把问题稍微改变一下:如果一共有4根柱子,
而不是3根,那么至少需要移动盘子多少次,才能把所有的盘子从第1根柱子移动到第4根柱子上呢?

为了编程方便,您只需要输出这个结果mod 10000的值。

输入
一个正整数n。(0<n<=50000)

输出
一个正整数,表示把n个盘子从第1根柱子移动到第4根柱子需要的最少移动次数mod 10000的值。

样例输入
15
样例输出
129

这道题一看到题,就是dp

那么

按照三塔问题的思路设dp(i)表示把i个盘子从一个柱子通过其他两个柱子移动到第四根柱子,在移动的时候我们发现,这还要用到3塔问题,那么我们应该预处理一下三塔问题

这以我们用f(i)表示把前i个盘子从一根柱子通过其他一根柱子移动到第三根柱子。

dp(i)=2(dp(i-1-k)*f(k))+1(0<=k<i)

由于最后是求出余数的最大值,那么用这个方程的话,就不满足同余定理,只能有高精度来算。高精度的话这道题超时很严重。

这时候打出前100的数据,仔细看可以发现 两个数之间的差值为2 2 4 4 4 8 8 8 8 16 16 16 16 16……找出这个的话,问题很easy了。

#include<cstdio>
#include<algorithm>
using namespace std;
const int mod = 10000;
const int Max_N = 50002;
int dp[Max_N];
int main()
{
    int i , j = 0, k = 2, t = 2;
    dp[1] = 1;
    for(i = 2;i <= Max_N-2;i++){
        j++;
        dp[i] = (dp[i - 1] + t) % mod;
        if(j == k){
            j = 0;
            k++;
            t *= 2;
            t %= mod;
        }
    }
    int n;
    while(scanf("%d",&n)!=EOF) printf("%d",dp[n]);
    return 0;
}

我们发现当一个操作性很强的dp题目出现时,我们可以通过找规律优化

posted @ 2017-09-21 14:40  star_eternal  阅读(590)  评论(0编辑  收藏  举报