UVALive 4050 Hanoi Towers

题目大意:3个桩的汉诺塔,每个数据给你一个n,表示盘子的个数,所有盘子起先都是在 A 上,给你一个列表,6个成对的字母,比如 AB 是表示把 A 顶上的盘子移动到 B 上,它整个流程是这样的:从头开始走那个表,找到第一个合法的移动(就是普通汉诺塔的规则一样,再加上后面的那个条件),然后就退出,又从头开始走第二遍表。这里还有另外一个条件,就是同一个盘子不能被连续的移动两次(in a row 原来是连续的意思,一直以为是同一行的意思,⊙﹏⊙b汗)。最后让你输出步数。

思路:设 d[ i ] 表示把 i 个盘子移好的步数, d[ i ] = x*d[ i - 1] + y ,x、y为未知变量,用模拟求出1个、2个、3个盘子移好需要的步数,然后列方程解出 x、y,d[ 1 ] = 1,最后一遍地推就好。

为什么就这样设两个未知量解出来就好了,也就是为什么它一定满足这个关系式,我也不知道,因为上面那个思路是我自己看一个大神的代码纯YY出来的。。= =  我只知道 如果是普通的汉诺塔 d[ i ] = 2*d[ i - 1] + 1,但是这道题目就这样设两个未知量 x、y搞搞就好了,真的想不明白,难道是类比YY?如果有哪位大神有幸光临的话,希望能不吝赐教,小弟不胜感激~~

代码如下(按照那个思路,模仿某大神写的):

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

typedef long long lld;

typedef pair<int,int> PII;

#define MP make_pair

vector < PII > al;

int is_legel(vector <int> a,vector <int> b)
{
    if(a.empty()) return 0;

    if(b.empty() || a.back() < b.back())
        return 1;

    return 0;
}

int get_val(int k)
{
    vector <int> p[3];
    for(int i = k;i>=1;i--) p[0].push_back(i);
    int step = 0;
    int pl = -1;
    while(p[1].size() != k && p[2].size() != k)
    {
        step ++;
        for(int i = 0;i<al.size();i++)
        {
            int from = al[i].first,to = al[i].second;
            if(is_legel(p[from],p[to]))
            {
                if(pl == p[from].back()) continue;
                pl = p[from].back();
                p[to].push_back(p[from].back());
                p[from].pop_back();

                break;
            }
        }

    }
    //printf("k = %d,step = %d\n",k,step);
    return step;
}

int val[5];

char str[11];

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        al.clear();
        for(int i = 0;i<6;i++)
        {
            scanf("%s",str);
            al.push_back(MP(str[0]-'A',str[1]-'A'));
        }
        for(int i = 1;i<=3;i++)
            val[i] = get_val(i);
        int x = (val[3] - val[2])/(val[2] - val[1]);
        int y = val[3] - val[2]*x;
        lld ans = 1;
        for(int i = 2;i<=n;i++)
            ans = ans*x + y;
        printf("%lld\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值