哈诺塔题型问题+uva10795+URAL 2029

哈诺塔基本算法:

将A上的n-1个借助C移到B,再将第n个盘子移到C,最后将B上的n-1个盘子借助A移到C。

得出的规律性结论:把n个盘子从A移到C的次数是2的n次方-1

#include<bits/stdc++.h>
using namespace std;
int cnt=0;
int a=1,b=2,c=3;
int f(int n,int a,int c,int b){
    if(n==1) {
        ++cnt;
        printf("%d %d %d\n",n,a,c);
        return cnt;
    }
    f(n-1,a,b,c);
    printf("%d %d %d\n",n,a,c);
    ++cnt;
    f(n-1,b,c,a);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        cnt=0;
        f(n,a,c,b);
        printf("cnt==%d\n",cnt);
        //把n个从A移到C的次数是2的n次方-1
    }
    return 0;
}
uva10795:

给定了初始和最终状态,求移动次数,并且规定盘子大小的次序始终是从小到大

首先判断移动第k个盘子时:先将k-1个移动到非目标方,然后把k移动到目标方,移动k-1个盘子的次数是2的k-1次方

然后:定义参考局面,就是移动k-1后的状态

最后:根据移动可逆,所求次数就是初始状态移到参考局面+最终状态移到参考局面+最后移动的第个k盘子

#include<bits/stdc++.h>
using namespace std;
int start[65];
int Final[65];
long long f(int *start,int k,int Final_)
{
    if(k==0) return 0;
    if(start[k]==Final_) return f(start,k-1,Final_);
    else return f(start,k-1,6-Final_-start[k])+(1LL<<(k-1));
}
int main()
{
    int n,kase=1;
    while(~scanf("%d",&n)&&n){
        long long ans=0;
        for(int i=1;i<=n;i++) scanf("%d",&start[i]);
        for(int i=1;i<=n;i++) scanf("%d",&Final[i]);
        int k=n;
        while(k>=1&&start[k]==Final[k]) k--;
        if(k>=1){
             ans = f(start,k-1,6-Final[k]-start[k])+f(Final,k-1,6-Final[k]-start[k])+1;
        }
        printf("Case %d: %lld\n",kase++,ans);
    }

    return 0;
}
URAL 2029

此题就是上一个题的变形,初始状态在题意里已经给出。

#include<bits/stdc++.h>
using namespace std;
char start[65];
char Final[65];
long long f(char *start,int k,char Final_)
{
    if(k==0) return 0;
    if(start[k]==Final_) return f(start,k-1,Final_);
    else return f(start,k-1,'A'+'B'+'C'-Final_-start[k])+(1LL<<(k-1));
}
int main()
{
    int n,kase=1;
    scanf("%d",&n);
        long long ans=0;
        for(int i=1;i<=n;i++) start[i]='A'; getchar();
        for(int i=1;i<=n;i++) scanf("%c",&Final[i]);
        int k=n;
        while(k>=1&&start[k]==Final[k]) k--;
        if(k>=1){
             ans = f(start,k-1,'A'+'B'+'C'-Final[k]-start[k])+f(Final,k-1,'A'+'B'+'C'-Final[k]-start[k])+1;
        }
        printf("%lld",ans);


    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值