zoukankan      html  css  js  c++  java
  • UVa 10795

    题目大意:给出n,表示说有n个大小不同的盘子,然后再给出每个盘子的初始位置和目标位置,要求计算出最少的步数使得每个盘子都移动到它的目标位置。

    分析:  首先找最大不在目标柱子上的盘子K,因为如果最大的盘子在目标柱子上它不需要移动,也不碍事。

    因此问题就成了把K移动到目标柱子,把1到(k-1)移动到中转柱子,所以假设K从A移动到B,A只有K,B是空的,C上面是K-1到1,把这个局面称为参考局面。因为移动是对称的,所以从参考局面移到目标局面与目标局面移到参考局面是一样的步数。

    所以问题变成答案=从初始局面移到参考局面步数+目标局面移到参考局面步数+1;

    需要写一个函数f(P,i,final),表示已知个盘子的初始柱面编号数组为P,把1到i移动到final的步数,本题答案是f(start,k-1,6-start[k]-finish[k])+f(finish,k-1,6-start[k]-finish[k])+1;

    计算f(P,i,final),若p[i]=final,则f(P,i,final)=f(P,i-1,final);否则需要把前i-1个盘子挪到中转盘去,将盘子i移到柱子final去,做后把前i-1个盘子从中转盘移到柱子final.。最后一步是把i-1个盘子从一个柱子移到另一个柱子,根据旧汉诺塔问题,这个步骤需要2^(i-1)-1步,加上移动盘子i那一步,一共需要2^(i-1)步。

    f(P,i,final)=f(P,i-1,6-p[i]-final)+2^(i-1);

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define MAXN 100
    #define LL long long
    using namespace std;
    int st[MAXN],ed[MAXN];
    LL fun(int *p,int i,int final)
    {
    if(i==0)return 0;
    if(p[i]==final)return fun(p,i-1,final);
    return fun(p,i-1,6-final-p[i])+(1LL<<(i-1));
    }
    int main()
    {
    int n;
    int cas=1;
    while(~scanf("%d",&n)&&n)
    {
    for(int i=1; i<=n; i++)
    scanf("%d",&st[i]);
    for(int i=1; i<=n; i++)
    scanf("%d",&ed[i]);
    int k=n;
    while(st[k]==ed[k]&&k)k--;
    LL ans=0;
    if(k!=0)
    {
    int tem=6-st[k]-ed[k];
    ans=fun(st,k-1,tem)+fun(ed,k-1,tem)+1;
    }
    printf("Case %d: %lld ",cas++,ans);
    }
    return 0;
    }

  • 相关阅读:
    Flutter高仿微信项目开源-具即时通讯IM功能
    flutter 如何实现文件读写(使用篇)
    这是我的第一篇博客,测试文章
    对于ServiceManager的理解
    Class文件结构
    App进程的启动
    对于SystemServer的理解
    对于Zygote的理解
    Git内部原理浅析
    二叉搜索树(BST)基本操作
  • 原文地址:https://www.cnblogs.com/tsw123/p/4324198.html
Copyright © 2011-2022 走看看