POj 3601 Tower of Hanoi 汉诺塔(贪心)

题意:汉诺塔问题,不过其中加了一个条件,就是盘子可以有相同的

可以发现,当移动第i 种盘子时&& num[i]>=2得到的是逆序的,但是题目要求不能改变顺序,所以必须处理

1.先考虑不按顺序的情况为 dp1[i]=dp1[i-1]*2+num[i]  ,num[i]为相同盘子的个数

公式得来:如果从A到C轴,借助B轴,i种盘子,要先把i - 1种移动到 B, 需要dp1[i - 1],然后把第i种移动到C,需要num[i],然后再把i - 1种从B移动到C,需要dp1[i - 1]
所以得到dp1[i]=dp1[i-1]*2+num[i] .

2.考虑按顺序的情况为 dp2[i]=2*dp1[i-1]+2*num[i]+dp2[i-1]

公式得来:把num[1] - 1个移动到辅助轴,这时这num[1] - 1个盘子的顺序颠倒了,然后把第num[1]中最后一个移动到目标轴,然后把辅助轴上的移动回来,再次颠倒,恢复顺序,得到dp2[1] = 2 * (num[1] - 1) +1。
对于dp2[i],
如果x[i] == 1,那么第i种就不需要考虑顺序(只有一种),所以dp2[i] = dp1[i]
否则,第i种要调动2次,保证顺序不变。
还是从A到C轴,借助B轴,i种盘子
把i - 1种不考虑顺序移到C,需要dp1[i - 1].
把第i种从A移动到B,需要num[i](颠倒顺序),
把i - 1种不考虑顺序移到A(腾出C),需要dp1[i - 1].
把第i种从B移动到C,需要num[i](顺序恢复)
把i - 1种考虑顺序移到C,需要dp2[i - 1].
所以有dp2[i] = 2 * dp1[i - 1] +2 * num[i] +dp2[i - 1]
最后答案是dp2[n].

代码:

#include 
#include 
using namespace std;
int dp1[105];
int dp2[105];
int num[105];
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)
        scanf("%d",&num[i]);
        dp1[1]=num[1];//dp1不考虑顺序
        for(int i=2;i<=n;i++)
        dp1[i]=(2*dp1[i-1]+num[i])%m;
        dp2[1]=2*(num[1]-1)+1;//考虑顺序
        for(int i=2;i<=n;i++)
        {
            if(num[i]==1)
            dp2[i]=dp1[i]%m;
            else
            dp2[i]=(2*dp1[i-1]+2*num[i]+dp2[i-1])%m;
        }
        printf("%d\n",dp2[n]);
    }
    return 0;
}


你可能感兴趣的:(贪心)