• 汉诺塔问题 hdu 2064 && hdu1997


    hdu 1997汉诺塔

    题目分析:

    转自:http://lcc3536.blog.163.com/blog/static/132469917201132283640123/

    1)  最初我们要判断一下是不是已经完全放好了,这样就不用考虑是不是最优化了, 因为都已经放好了,肯定是最合法的! 或者说全部在 A 上,这是还没开始动作的一个状态,所以也是合法的!
    2)  否则我们  要对每次状态的最大的那个进行判断,因为我们知道,汉诺塔最大的那个不可能停在 B 上,(假设 最初的时候都在 A 上,要移到 C 上去!),只可能在 A 或者 C 上面!如果是放在 B 上面,停止判断,直接断定他非法~这样我们得出了第二个判段依据!
    3) 如果最大的在 A 上面,我可以想到的是,他还没有放在 C 上,此时这个状态的上面一系列状态都是想把其他的放在 B 上,然后就可以把 A 放到 C 上了,所以我们在这里做出更新,因为他上面一系列动作都是想让 A 上面的除最大的外都放到 B 上面去,所以,我们这个时候往上考虑,对 N-1 进行 判断!这个时候动作的方向是 A->B 所以为了统一操作我们得把 B 跟C互换
    4) 如果最大的在 C 上面,这时候倒数第二大的不是放在 B 上就是 C 上,我们要把要把倒数第二大的以及其他的放在 C 上,这时候的动作方向是 B—>C ;所以把 A 跟 B 交换一下!

    View Code
    #include<iostream>
    using namespace std;
    int main()
    {
    int a=1,b=2,c=3;
    int h[4][65],n[4],one[4],N;
    int cas;
    cin
    >>cas;
    while(cas--)
    {
    int flag=0;
    one[a]
    =one[b]=one[c]=1;
    cin
    >>N;
    cin
    >>n[a];
    for(int i=one[a];i<=n[a];i++)
    cin
    >>h[a][i];
    cin
    >>n[b];
    for(int i=one[b];i<=n[b];i++)
    cin
    >>h[b][i];
    cin
    >>n[c];
    for(int i=one[c];i<=n[c];i++)
    cin
    >>h[c][i];
    while(1)
    {
    if(n[a]==N||n[c]==N)
    {
    flag
    =1;break;
    }
    if(n[b]>0&&h[b][one[b]]==N)
    {
    flag
    =0;break;
    }
    if(n[a]>0&&h[a][one[a]]==N)//交换b和c
    {
    N
    --;one[a]++;
    n[a]
    --;
    int t=b;
    b
    =c;c=t;
    continue;
    }
    if(n[c]>0&&h[c][one[c]]==N)//交换a和b
    {
    N
    --;one[c]++;
    n[c]
    --;
    int t=a;
    a
    =b;b=t;
    continue;
    }
    }
    if(flag)cout<<"true"<<endl;
    else cout<<"false"<<endl;
    }
    return 0;
    }

    hdu 2064 汉诺塔III

    题目分析:

    汉诺塔是我很喜欢玩的一个游戏。
    如果规则没这么变态,允许直接从1跨越到3,那n个盘最少需要2n - 1次。
    这个公式可以递推得到,很容易的,你可以试一下,这里就不阐述了。

    而这一题同样可以用递推得到。我们先来看看下面一组图,了解一下如何把n个盘从1搬到3。

    我们设f(n)为把n个盘从1移到3所需要的步数,当然也等于从3移到1的步数。
    看什么的图就知道,要想把第n个盘从1移到3,需要想把前n-1个从1移动3,再从3->1最后再1->3。
    而第n个盘要从1->2->3经历2步。
    ∴f(n) = 3 × f(n-1) + 2;
      f(1) = 2;

    hdu2064
    #include<iostream>
    using namespace std;
    __int64 f[
    36];
    void init()
    {
    f[
    1]=2;
    for(int i=2;i<=35;i++)
    f[i]
    =3*f[i-1]+2;
    }
    int main()
    {
    int n;
    init();
    while(scanf("%d",&n)==1)
    {
    printf(
    "%I64d\n",f[n]);
    }
    return 0;
    }
  • 相关阅读:
    用Asp.Net实现类似DWR的功能
    Icesword FAQ端口 进程 服务篇
    用脚本实时显示Linux网络流量
    为DropDownList 添加optgroup分组以及为ListItem 加式样
    C# 中Treeview无限级目录实现
    .NET 2.0 WinForm Control DataGridView 编程36计(一)
    如何:从 Windows 窗体 DataGridView 控件中移除自动生成的列
    分组显示的select下拉选框
    如何用命令行查找并快速定位ARP病毒母机
    在.NET上如何根据字符串动态创建控件
  • 原文地址:https://www.cnblogs.com/nanke/p/2171165.html
Copyright © 2020-2023  润新知