• UVA 10795 A Different Task


    https://vjudge.net/problem/UVA-10795

    题目

    输入两个状态,把汉诺塔从一个状态一直移动到另外一个状态最少需要几步?

    例如从左图到右图需要最少6步

    题解

    首先考虑最大的圆盘(k)如何移动到目标柱子上。如果就在目标柱子就不需要移动,考虑下一个最大的(k=k-1)。

    肯定是把小于它的圆盘(<k)移动到对于最大的圆盘(k)来说非起始并且是非目标的柱子中(1+2+3-s-t),然后把最大的圆盘(k)移动到目标柱子中。

    这一步是必须经过的,而且没有其他的走法。

    那么可以在起始状态移动一次最大的,目标状态移动一次最大的,这样就会到达同一状态。

    现在的问题是如何把编号为0~n的圆盘移动到一个指定的柱子中。

    只有一个圆盘的时候,直接判断

    仍然考虑最大的,如果本身就在指定的柱子,n--;

    否则,先把0~n-1的圆盘移动到起始柱子和指定的柱子以外的另外一个柱子,然后把n移动到指定的柱子,最后把0~n-1移动到指定的柱子,可以推公式得到最后这一步需要$2^{n-1}-1$步

    AC代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #include<unordered_map>
    #include<string>
    #define REP(i,a,b) for(register int i=(a); i<(b); i++)
    #define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
    #define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
    using namespace std;
    typedef long long ll;
    #define MAXN 67
    int st[MAXN], ed[MAXN];
    ll calc(int *P, int k, int j) {
    	if(k==-1) return 0;
    	if(P[k]==j) return calc(P,k-1,j);
    	return calc(P,k-1,6-P[k]-j)+(1ll<<(k+1-1));
    }
    int main() {
    	int n;
    	int kase=0;
    	while(~scanf("%d", &n) && n) {
    		REP(i,0,n) scanf("%d", &st[i]);
    		REP(i,0,n) scanf("%d", &ed[i]);
    		ll ans=0;
    		PERE(i,n-1,0) if(st[i]!=ed[i]) {
    			int other = 6-st[i]-ed[i];
    			ans = calc(st, i-1, other) + calc(ed, i-1, other) + 1;
    			break;
    		}
    		printf("Case %d: %lld
    ", ++kase, ans);
    	}
    }
    
  • 相关阅读:
    vue的组件名称问题
    vue引入js文件时报This dependency was not found:错误
    vue中input输入第一个字符时,光标会消失,需要再次点击才能输入
    vue中url带有#号键,去除方法
    vue路由机制导致的坑,坑,坑
    Python文件读取和数据处理
    python面向对象
    Python PIL库学习笔记
    汉诺塔的python 动画演示
    十九大报告词频分析
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12343484.html
Copyright © 2020-2023  润新知