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

水平方向上有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("请输入格子数:\n");
50 scanf("%d",&n);
51 printf("请输入%d个数:\n",n);
52 for(int k = 1;k <= n;k++)
53 {
54 scanf("%d",&cell[k]);
55 }
56 printf("过去的步骤一共 %d 步\n",Come(n,cell));
57 printf("回来的步骤一共是 %d 步\n",Back(n,cell));
58 }
59 system("Pause");
60 return 0;
61 }

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

posted on 2013-11-01 00:16  光明小天使  阅读(2114)  评论(0编辑  收藏  举报