【2016-2017 ACM-ICPC (ECNA 2016) G】That's One Hanoi-ed Teacher(思维)

题目链接:http://codeforces.com/gym/101196

 

题目大意:询问当前状态是否是最优方案中的一种,若是输出剩下还需多少步

 

题目思路:

汉诺塔的递归函数的写法是

dfs(a,c,b)

dfs(b,a,c)

分别是在a以c为辅助去b,在b以a为辅助去c

所以其实它呈现出的是一个二叉树的结构

首先根据汉诺塔的性质,最大的环要么在第一个柱子,要么在第三个柱子,如果在第二个柱子就说明这种方案不是最优方案

现在问题可以转换成它在二叉树的哪一个位置

如果是在左边那个状态的话,就说明右边那一个状态中的所有情况一定都还没有经历,都属于剩下要走的步数,那就加上这个状态中的所有步数,就是2^n种(n表示这个状态中的环的个数),然后继续递归这个状态寻找次大的情况,如果是右边那个状态,那啥也不知道,继续递归到次大的情况,由此就能获得所有的情况

 

以下是代码:

#include
 
using namespace std;
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
int n,x,z[105],flag;
ll ans;
void dfs(int a,int b,int c,int n){
    if(!n)return;
    if(z[n]==a){
        ans+=1ll<<(n-1);
        dfs(a,c,b,n-1);
    }
    else if(z[n]==c){
        dfs(b,a,c,n-1);
    }
    else flag=1;
}
int main()
{
    while(~scanf("%d",&n)){
        int num=n;
        rep(i,1,n)scanf("%d",&x),z[x]=1;
        scanf("%d",&n);num+=n;
        rep(i,1,n)scanf("%d",&x),z[x]=2;
        scanf("%d",&n);num+=n;
        rep(i,1,n)scanf("%d",&x),z[x]=3;
        ans=flag=0;
        dfs(1,2,3,num);
        if(flag){
            printf("No\n");
            continue;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

 

你可能感兴趣的:(思维)