• 跳棋(利用规范的数学方法)


    水平方向上有n个格子,格子上写着1到n的数字中的一个,游戏规则是:走到某一格,上面的数字假如是s,则可以选择跳到第s个格子或者前进一格,问你最少要走多少步才能到达最后一格并且返回起点。如:3 5 3 2 6 5 ,你去的时候可以一步一步到终点(5步),也可以一开始就跳到第三格,再一步一步到终点(4步),或者先前进一步再跳到第5格再一步一步地走(3步),最少是3步到达。然后要再返回的时候,最少步数的走法是,左移两步再跳到第二格再左移一步(4步),共7步。

    分析:刚开始做的时候没有头绪,用的基本等于猜的方法,比如从题中第一格开始,到第三格,然后返回来查是否还有大的数字(比如5),这种方法最后加了很多复杂的约束,最终也没能完美的做出这道题,在参考了网上的方法之后,发现自己太小白了以及数学真是牛逼的学科!对于此类题用的是数学归纳法证明操作到f[n]是1到n的最小步数。

    1.从第一步到第一步也就是f[1] = 0满足条件;

    2.假设从1到k步都满足f[k]是最小步数;

    3.假设1到n存在一个最优路径,而它的上一个格子是k,那么f[n] = f[k] + 1,否则从1到k一定可以走出比f[k]更小的最优路径,而这是不可能的。代码如下:

     1 #include "stdafx.h"
     2 #include <stdlib.h>
     3 const int Max = 100001;
     4 int count[Max] = {0};
     5 //用指针传入数组~真是好用就是还不知道风险,这个方法是计算出走过去需要多少步
     6 int Come(int n,int *a)
     7 {
     8 //初始化第一步到第一步需要0步.
     9 count[1] = 0;
    10 int k;
    11 //其他格子赋初值最大,这样在后面容易进行比较
    12 for(int s = 2;s <= n;s++)
    13     count[s] = Max;
    14 //由于每一次具有两个选择,向前或者跳到相应格子所以,从第一步开始计算。
    15 for(k = 1;k < n;k++)
    16 {
    17     //本格子的下一个格子需要多少步,比较count[k+1]和count[k] + 1取小值
    18     if(count[k + 1] > count[k] + 1)
    19         count[k +1] = count[k] + 1;
    20     //本格子跳到的相应格子需要多少步,比较count[a[k]]和count[k] + 1取小值
    21     if(a[k] > k && count[a[k]] > count[k] + 1)
    22         count[a[k]]  = count[k] + 1;
    23 }
    24 return count[n];
    25 }
    26 //同上
    27 int Back(int n,int *a)
    28 {
    29  count[n] = 0;
    30  int k;
    31 for(int s = n -1;s >= 1;s--)
    32     count[s] = Max;
    33 for(k = n;k > 1;k--)
    34 {
    35     if(count[k - 1] > count[k] + 1)
    36         count[k -1] = count[k] + 1;
    37     if(a[k] < k)
    38         count[a[k]]  = count[k] + 1;
    39 }
    40 return count[1];
    41 }
    42 int _tmain(int argc, _TCHAR* argv[])
    43 {    
    44 int n;
    45 //C语言不支持动态数组
    46 int cell[Max] = {0};
    47 while(scanf("%d",&n) != 0)
    48 {
    49 printf("请输入格子数:
    ");
    50 scanf("%d",&n);
    51 printf("请输入%d个数:
    ",n);
    52 for(int k = 1;k <= n;k++)
    53 {
    54 scanf("%d",&cell[k]);
    55 }
    56 printf("过去的步骤一共 %d 步
    ",Come(n,cell));
    57 printf("回来的步骤一共是 %d 步
    ",Back(n,cell));
    58 }
    59 system("Pause");
    60 return 0;
    61 }

    数学真的是一个牛逼的学科,想学好算法没有数学基础真的要走很多弯路,而且写出来的还不是好程序...在被虐的路上小白在进步。

  • 相关阅读:
    WindRiver workbench 做操步骤
    发现pci设备
    pci驱动与硬件通信
    推荐一款pascal 语言的web 开发工具
    Basic4android v2.70 发布
    如何制作 Basic4android 的库文件
    GoGoGo,哦哦哦,我获奖了..微软的双肩笔记本包~~
    爽,买到返程票了!
    去掉微软认证的WINDOWS盗版标志
    大四才醒悟太迟了吗
  • 原文地址:https://www.cnblogs.com/baikequanshu/p/3399783.html
Copyright © 2020-2023  润新知