鱼C论坛

 找回密码
 立即注册
查看: 2646|回复: 9

[已解决]关于欧拉计划第十八问

[复制链接]
发表于 2017-3-14 21:35:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
从下面的三角形的顶端开始,向下面一行的相邻数字移动,从顶端到底端的最大总和为23.



也就是 3 + 7 + 4 + 9 = 23.

找出从以下三角形的顶端走到底端的最大总和:



提示:以上图中共有16384条路径,所以你可以用穷举法。但是第67题是同样的题目,但是拥有100层。此时你不能再靠蛮力,你需要一个更便捷的方法。

求大神教育一波,怎么用C语言解决这个问题,我的想法是用递归一个个列举出来,但是不知道究竟怎么实现,想了两天了,没解决
最佳答案
2017-3-14 23:23:11
定义一个全局变量min用来存放最小值,初始化为0
void 递归函数(int i,int j,int sum) //用二维数组存放数据,以i j决定位置
{
判断i是否到底,若到底了,判断当min==0或min>sum,则让min=sum
调用自己(i+1,j,sum+a[i][j]);
调用自己(i+1,j+1,sum+a[i][j]);

}
int main()
{
int a[][]; //存放数据

调用递归函数(0,0,a[0][0]);
printf("%d",min)


}

思路大概这样,先来去睡了,如果没有解决到你的问题请见谅
bdddf5bebee7e6b2.png
7a2306fedb25856a.png
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2017-3-14 22:37:12 | 显示全部楼层
用递归的话几行就解决了,但效率比较低,因为把所有可能都跑过,复杂度是O(2^n)
好一点的算法是,因为每往下一层都可以找出走到目前这个位置的最小和,复杂度是O(n^2)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-3-14 22:41:31 | 显示全部楼层
fc1735 发表于 2017-3-14 22:37
用递归的话几行就解决了,但效率比较低,因为把所有可能都跑过,复杂度是O(2^n)
好一点的算法是,因为每往 ...

关键是我递归就是不会呀递归学得不好,老甲鱼又不更新作业,只能找题练习一下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-14 23:23:11 | 显示全部楼层    本楼为最佳答案   
定义一个全局变量min用来存放最小值,初始化为0
void 递归函数(int i,int j,int sum) //用二维数组存放数据,以i j决定位置
{
判断i是否到底,若到底了,判断当min==0或min>sum,则让min=sum
调用自己(i+1,j,sum+a[i][j]);
调用自己(i+1,j+1,sum+a[i][j]);

}
int main()
{
int a[][]; //存放数据

调用递归函数(0,0,a[0][0]);
printf("%d",min)


}

思路大概这样,先来去睡了,如果没有解决到你的问题请见谅
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-15 00:22:45 | 显示全部楼层
计算没一行时 先比较在加 要比 先加在比较的方法效率高一点   
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-3-15 11:19:38 | 显示全部楼层
fc1735 发表于 2017-3-14 23:23
定义一个全局变量min用来存放最小值,初始化为0
void 递归函数(int i,int j,int sum) //用二维数组存放数 ...

额,不好意思,不知道是不是我理解能力有点问题,能不能写的清晰一点,没有看懂
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-18 16:39:24 | 显示全部楼层
自由深渊 发表于 2017-3-15 11:19
额,不好意思,不知道是不是我理解能力有点问题,能不能写的清晰一点,没有看懂

100层时就不能用递归了
现在最高支持到24层^_^

很多地方都没有注释,希望你能看懂^_^

无标题.png

源.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "Tree.h"

  5. #define LAYER 24  // 24层是最大了 ^_^
  6. #define ITEM 9999999

  7. int tmp[LAYER + 1];
  8. unsigned long n = 0;

  9. static void set_array(Tree **T, int(*((*path)[ITEM]))[LAYER + 1], int c)
  10. {
  11.         if((*T)->lchild == NULL)
  12.         {
  13.                 tmp[c++] = (*T)->data;
  14.                 c = 1;

  15.                 (*path)[n++] = malloc(sizeof(int) * (LAYER + 1)); // 数组第0个元素存储总和
  16.                 (*path)[n] = NULL;
  17.                 memcpy(*(*path)[n - 1], tmp, (LAYER + 1) * sizeof(int));
  18.                 return;
  19.         }

  20.         tmp[c++] = (*T)->data;
  21.         set_array(&(*T)->lchild, path, c);
  22.         set_array(&(*T)->rchild, path, c);
  23. }

  24. static unsigned long get_item(int(*((*path)[ITEM]))[LAYER + 1])
  25. {
  26.         unsigned long ret = 0;
  27.         unsigned long c = 0;

  28.         while((*path)[c] != NULL)
  29.         {
  30.                 c++;
  31.                 ret++;
  32.         }

  33.         return ret;
  34. }

  35. static void free_array(int(*((*path)[ITEM]))[LAYER + 1])
  36. {
  37.         for(unsigned long i = 0; i < ITEM; i++)
  38.         {
  39.                 if((*path)[i] == NULL)
  40.                 {
  41.                         break;
  42.                 }

  43.                 free((*path)[i]);
  44.         }
  45. }

  46. int euler(Tree **T, int (**ret_path)[LAYER + 1])
  47. {
  48.         int(*((*path)[ITEM]))[LAYER + 1];
  49.         path = malloc(sizeof(int) * ITEM);

  50.         set_array(T, path, 1); // 数组第0个元素存储总和

  51.         // 计算每条路径的和
  52.         unsigned long item = get_item(path);
  53.         for(unsigned long i = 0; i < item; i++)
  54.         {
  55.                 (*(*path)[i])[0] = 0;
  56.                 for(int j = 1; j <= LAYER; j++)
  57.                 {
  58.                         (*(*path)[i])[0] += (*(*path)[i])[j];
  59.                 }
  60.         }

  61.         // 查找最大
  62.         int max = (*(*path)[0])[0];
  63.         int index = 0;
  64.         for(unsigned long i = 0; i < item; i++)
  65.         {
  66.                 if(max < (*(*path)[i])[0])
  67.                 {
  68.                         index = i;
  69.                         max = (*(*path)[i])[0];
  70.                 }
  71.         }


  72.         memcpy(*ret_path, (*path)[index], sizeof(int) * (LAYER + 1));
  73.         free_array(path);
  74.         free(path);

  75.         return max;
  76. }

  77. int main(void)
  78. {
  79.         int(*ret_path)[LAYER + 1] = malloc(sizeof(int) * (LAYER + 1));

  80.         Tree *T;
  81.         InitTree(&T);
  82.         CreateTree(&T, LAYER);
  83.         PrintTree(&T);
  84.         putchar('\n');

  85.         printf("最大和是:%d\n", euler(&T, &ret_path));

  86.         printf("输出路径:\n");
  87.         for(int i = 1; i <= LAYER; i++)
  88.         {
  89.                 printf("%.3d -> ", (*ret_path)[i]);
  90.         }

  91.         // 退掉最后一个箭头
  92.         printf("\b\b\b\b");
  93.         printf("    ");

  94.         putchar('\n');

  95.         free(ret_path);
  96.         DestroyTree(&T);

  97.         return 0;
  98. }
复制代码


Tree.c
  1. #include "Tree.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <time.h>

  6. static int get_rand()
  7. {
  8.         return 1 + (int)(999.0*rand() / (RAND_MAX + 0.0));
  9. }

  10. void InitTree(Tree **T)
  11. {
  12.         (*T) = malloc(sizeof(Tree));
  13.         (*T)->data = get_rand();
  14.         (*T)->lchild = NULL;
  15.         (*T)->rchild = NULL;
  16.         (*T)->degree = NULL;


  17.         srand((unsigned)time(NULL)); // 初始化一下随机数
  18. }


  19. static Tree *get_lchild(Tree **T)
  20. {
  21.         return (*T)->lchild->rchild;
  22. }

  23. static void set_left_degree(Tree **T, Tree *rchild)
  24. {
  25.         (*T)->lchild->degree = rchild;
  26. }

  27. static void create_left_child(Tree **T, int layer)
  28. {
  29.         if(layer == 1)
  30.         {
  31.                 return ;
  32.         }

  33.         (*T)->lchild = malloc(sizeof(Tree));
  34.         (*T)->lchild->data = get_rand();
  35.         (*T)->lchild->lchild = NULL;
  36.         (*T)->lchild->rchild = NULL;
  37.         (*T)->lchild->degree = NULL;
  38.         create_left_child(&(*T)->lchild, layer - 1);
  39. }

  40. static void create_right_child2(Tree **T, int layer)
  41. {
  42.         if(layer == 1)
  43.         {
  44.                 return ;
  45.         }

  46.         (*T)->rchild = malloc(sizeof(Tree));
  47.         (*T)->rchild->data = get_rand();
  48.         (*T)->rchild->lchild = get_lchild(T);
  49.         (*T)->rchild->rchild = NULL;
  50.         (*T)->rchild->degree = NULL;
  51.         set_left_degree(T, (*T)->rchild);
  52.         create_right_child2(&(*T)->rchild, layer - 1);
  53. }

  54. static void create_right_child(Tree **T, int layer)
  55. {
  56.         if((*T)->lchild == NULL)
  57.         {
  58.                 return ;
  59.         }

  60.         create_right_child(&(*T)->lchild, layer - 1);

  61.         create_right_child2(T, layer);

  62. }

  63. void CreateTree(Tree **T, int layer)
  64. {
  65.         create_left_child(T, layer);
  66.         create_right_child(T, layer);
  67. }

  68. void DestroyTree(Tree **T)
  69. {
  70.         Tree *pp = *T;
  71.         Tree *p = pp->lchild;
  72.         Tree *tmp;

  73.         while(p != NULL)
  74.         {
  75.                 p = pp->lchild;
  76.                 while(pp != NULL)
  77.                 {
  78.                         tmp = pp;
  79.                         pp = pp->degree;
  80.                         free(tmp);
  81.                 }

  82.                 pp = p;
  83.         }

  84.         *T = NULL;
  85. }

  86. static void print_space(int max_degree, int i)
  87. {
  88.         int n = (max_degree * 4 / 2 - 2) - (i - 1) * 4 / 2;
  89.         while(n--)
  90.         {
  91.                 printf(" ");
  92.         }
  93. }

  94. static int get_degree(Tree **T)
  95. {
  96.         int ret = 0;
  97.         Tree *p = *T;

  98.         while(p != NULL)
  99.         {
  100.                 ret++;
  101.                 p = p->degree;
  102.         }

  103.         return ret;
  104. }

  105. static int get_max_degree(Tree **T)
  106. {
  107.         int ret = 0;
  108.         Tree *p = *T;


  109.         while(p->lchild != NULL)
  110.         {
  111.                 p = p->lchild;
  112.         }

  113.         while(p != NULL)
  114.         {
  115.                 ret++;
  116.                 p = p->degree;
  117.         }

  118.         return ret;
  119. }


  120. void PrintTree(Tree **T)
  121. {
  122.         Tree *p = *T;
  123.         Tree *pp = p;
  124.         int max_degree = get_max_degree(T);

  125.         while(p != NULL)
  126.         {
  127.                 pp = p;
  128.                 print_space(max_degree, get_degree(&p));
  129.                 while(pp != NULL)
  130.                 {
  131.                         printf("%.3d ", pp->data);
  132.                         pp = pp->degree;
  133.                 }
  134.                 putchar('\n');

  135.                 p = p->lchild;
  136.         }
  137. }
复制代码


Tree.h
  1. #ifndef _TREE_H
  2. #define _TREE_H

  3. #define OK 1
  4. #define ERROR 0
  5. #define TRUE 1
  6. #define FALSE 0

  7. //typedef int Status;        /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
  8. typedef int ElemType;

  9. typedef struct Tree
  10. {
  11.         ElemType data;
  12.         struct Tree *lchild;
  13.         struct Tree *rchild;
  14.         struct Tree *degree;
  15. } Tree;

  16. void InitTree(Tree **T);
  17. void CreateTree(Tree **T, int layer);
  18. void PrintTree(Tree **T);
  19. void DestroyTree(Tree **T);

  20. #endif
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-3-18 16:54:39 | 显示全部楼层
人造人 发表于 2017-3-18 16:39
100层时就不能用递归了
现在最高支持到24层^_^

感谢  
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-18 17:00:36 | 显示全部楼层
这种题目可以用动态规划完成
  1. #include <stdio.h>
  2. int main(int argc, char *argv[])
  3. {
  4.         int arr[15][15] = {
  5.                 {3},
  6.                 {7, 4},
  7.                 {2, 4, 6},
  8.                 {8, 5, 9, 3}
  9.         };
  10.         for(int i=1; i<4; ++i)
  11.         {
  12.                 for(int j=0; j<=i; ++j)
  13.                 {
  14.                         int left = 0;
  15.                         if(j>0)
  16.                                 left = arr[i-1][j-1];
  17.                         int right = 0;
  18.                         if(j<i)
  19.                                 right = arr[i-1][j];
  20.                         arr[i][j] += left > right ? left : right;
  21.                 }
  22.         }
  23.         int nMax = arr[3][0];
  24.         for(int i=1; i<4; ++i)
  25.         {
  26.                 nMax = nMax > arr[3][i] ? nMax : arr[3][i];
  27.         }
  28.         printf("%d\n", nMax);
  29.         return 0;
  30. }
复制代码

基础代码就是这样
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-18 17:01:06 | 显示全部楼层
复杂度是 O(n)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-9 19:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表