zoukankan      html  css  js  c++  java
  • 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);
    	}
    }
    
  • 相关阅读:
    redis数据结构
    XMAPP 的安装与配置
    Android 工具类 异常处理类CrashHandler
    Android Config通用类来记录信息
    Android AppUtil通用类
    Android 用Chrome浏览器打开url 自定义样式
    Diycode开源项目 如何解决InputMethodManager造成的内存泄漏问题
    Diycode开源项目 SitesListFragment分析
    Diycode开源项目 NodeListFragment分析
    Diycode开源项目 搭建可以具有下拉刷新和上拉加载的Fragment
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12343484.html
Copyright © 2011-2022 走看看