最简单的动态规划之POJ1063

    对于算法的五大分类,基本上就是递归和回溯,分治,动态规划,贪心,搜索和剪枝。
最近写程序写的少,算法看的也不多,用个最简单的程序总结一下动态规划。顺便测试一下刚刚下的Syntax Highlighter 插件好不好用。
原题见: http://acm.pku.edu.cn/JudgeOnline/problem?id=1163  求从顶端到低端的最长路径(约束条件为:沿对角线方向走)

简单的说输入就是下面下面这个下三角矩阵:
5 //As is known to all, 代表一共有5行数据
7
3  8
8  1  0
2  7  4  4
4  5  2  6  5
输出为:从顶端的7开始,沿着左斜下方或者右斜下方走,走到低端的最长路径是多少?
针对该用例的输出(用人脑走一遍,显而易见):
30

这个最简单的动态规划题目满足了动态规划的四个条件:
1. Characterize the structure of an optimal solution.  有公共的子问题
2. Recursively define the value of an optimal solution.  能递归的定义子问题的最优解
3. Compute the value of an optimal solution in a bottom-up fashion. 能自底向上的求解
4. Construct an optimal solution from computed information.   能通过计算信息构造出最优解

这里用的也是最最简单的填表法,通过输入填表,然后自底向上的构造最优解。

程序很简单,如下:

01#include <stdio.h>
02#include <assert.h>
03#define MAXCOL 101
04#define MAXROW 101
05 
06int main()
07{
08    int n, num;
09    int i = 0, j = 0;
10    int a[MAXROW][MAXCOL];
11    int max = 0;
12 
13    scanf("%d", &n);
14    assert(n < MAXCOL);
15 
16    for(i = 0; i < n; i++)
17      for( j = 0; j <=i; j++)
18     {
19         scanf("%d", &num);
20        a[i][j] = num;
21     }         
22 
23    for( i = n-2; i>=0; i--)
24       for(j = 0; j <= i; j++)
25       {
26             max = a[i+1][j] > a[i+1][j+1]? a[i+1][j]: a[i+1][j+1];
27             a[i][j] = a[i][j] + max;
28       }
29 
30    i++;
31    j--;
32    printf("%d", a[i][j]);     
33 
34    return 0;
35}</assert.h></stdio.h>

关于路径求解还有一道题,就是一个二叉树,让求从根节点到所有叶子节点中最长的路径。
思路基本上就是后序遍历,然后在遍历的过程中加入叶子节点的值,每当节点出栈的时候,相应的路径值也递减
顺手练习了两种递归的创建树的方法,第一种好一些,容易管理内存。

001#include <cstdio>
002#include <iostream>
003#include <stack>
004 
005using namespace std;
006 
007typedef struct bNode
008{
009     int data;
010     bool tag;
011     struct bNode *left;
012     struct bNode * right;
013}BNode;
014typedef BNode * BTree;
015 
016//method1:create tree
017//@param: the reference of pointer root
018//@return: no return value
019void CreateTree(BTree &root)
020{
021      int data;
022 
023      scanf("%d", &data);
024      if(data == -1)
025         root = NULL;
026      else
027      {
028          root = (BTree)malloc(sizeof(BNode));
029          root->data = data;
030          root->tag = 0;
031          root->left = root->right = NULL;
032 
033          CreateTree(root->left);
034          CreateTree(root->right);
035      }
036}
037//@method2: Create a tree recursively
038//@params: void
039//@return: BNode pointer point to the root of the tree
040BNode * CreateNode()
041{
042      int data;
043      scanf("%d", &data);
044 
045      if(data == -1)
046         return NULL;
047      else
048      {
049          BTree root = (BTree)malloc(sizeof(BNode));
050          root->data = data;
051          root->tag = 0;
052          root->left = CreateNode();
053          root->right = CreateNode();
054 
055          return root;
056      }
057}
058//@function: to get the biggest sum of the branch
059void BranchSum(BTree root)
060{
061     stack<bnode *=""> s;
062     BTree p;
063     int pathval = 0;
064     int sum = 0;
065 
066     while(root!=NULL || (!s.empty()) )
067     {
068         while(root!=NULL)
069         {
070              s.push(root);
071              pathval = pathval + root->data;
072              root = root->left;
073         }
074         if(pathval > sum)
075         {
076            sum = pathval;
077         }
078 
079         if(!s.empty())
080         {
081              root = s.top();
082 
083              if(root->tag == 1)
084              {
085                  printf("%5d", root->data);
086                  pathval = pathval - root->data;
087                  s.pop();
088                  root = NULL;
089              }
090              else   //turn to search the right child tree
091              {
092                  root->tag = 1;
093                  root = root->right;
094              }
095         }
096     }
097       printf("\nsum is %5d\n", sum);
098}
099 
100int main()
101{
102    BTree root = NULL;
103    printf("Create a tree \n");
104 
105    //CreateTree(root);
106    root = CreateNode();
107    BranchSum(root);
108 
109     return 0;
110}
111</bnode></stack></iostream></cstdio>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值