• UVA 10795 A Different Task(模拟)


    题目链接:https://vjudge.net/problem/UVA-10795

    一道比较有思维含量的一道题:

    注意一种分治的思想和“除了柱子x和柱子y之外的那个柱子”编号的问题。

    首先在初始局面和目标局面中找到所在柱子不同的盘子中编号最大的一个,设为$k$,那么$k$必须要移动。

    假设$k$要从柱子一移动到柱子二,在$k$移动之前,由于编号比$k$大的盘子不需要移动,也不会碍事,所以把它们当作不存在。编号比$k$小的只能在柱子三上。

    那么这时柱子一上只有$k$,柱子二为空,柱子三上有$1,2,3...k-1$。这个局面成为“参考局面”。

    而盘子的运动是可逆的,所以根据对称性,只要求出初始局面和目标局面移动到“参考局面”的步数和再加一即可。

    那么写一个函数$f(P,i,final)$,($P[i]$表示盘子$i$的柱子编号,$f$表示把$1,2,3....i-1$全部移到柱子$final$所需步数)。

    则$ans=f(start,k-1,6-start[k]-finish[k])+f(finish,k-1,6-start[k]-finish[k])+1$。

    其中注意“除了柱子x和柱子y之外的那个柱子”编号为$6-x-y$。(普通汉诺塔结论)

    最后进行递归:

    $i=0 -> 0$

    $P[i]=final -> f(P,i,final)=f(P,i-1,final)$

    $f(P,i,final)=f(P,i-1,6-P[i]-final)+2^{i-1}$

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 
     4 using namespace std;
     5 typedef long long ll;
     6 
     7 const int maxn=70;
     8 int n,start[maxn],finish[maxn];
     9 
    10 ll f(int *P,int i,int final){
    11     if(i==0) return 0;
    12     if(P[i]==final) return f(P,i-1,final);
    13     return f(P,i-1,6-P[i]-final)+(1LL<<(i-1));
    14 }
    15 
    16 int main(){
    17     int kase=0;
    18     while(scanf("%d",&n)==1&&n){
    19         for(int i=1;i<=n;i++) scanf("%d",&start[i]);
    20         for(int i=1;i<=n;i++) scanf("%d",&finish[i]);
    21         int k=n;
    22         while(k>=1&&start[k]==finish[k]) k--;
    23         ll ans=0;
    24         if(k>=1){
    25             int other=6-start[k]-finish[k];
    26             ans=f(start,k-1,final)+f(finish,k-1,final)+1;
    27         }
    28         printf("Case %d: %lld
    ",kase,ans);
    29     }
    30     return 0;
    31 }
    AC代码
  • 相关阅读:
    JS 一键复制功能实现
    移动端点击弹窗后禁止页面滑动
    ui库地址总结
    react源码解析20.总结&第一章的面试题解答
    react源码解析19.手写迷你版react
    react源码解析18事件系统
    react源码解析17.context
    react源码解析16.concurrent模式
    react源码解析15.scheduler&Lane
    react源码解析14.手写hooks
  • 原文地址:https://www.cnblogs.com/New-ljx/p/12293213.html
Copyright © 2020-2023  润新知