计蒜客-程序设计竞赛入门
2016-07-18 11:19
204 查看
数塔问题
问题描述:
9 12 15 10 6 8 2 18 9 5 19 7 10 4 15
上面这张图是一个数塔问题的例子。每次从顶部元素,就是上图中的9出发,每次可以走到下面相邻的两个节点,比如从9往下相邻的是12和15,6往下相邻的是18和9。找到一条从顶部到底部的路径,使得路径上的数值和最大。 一个直观的贪心策略是每次向下走都选择较大的那一个,得到的一个解是9+15+8+9+10=51,然而我们发现最优的解是9+12+10+18+10=59,也就是说这道题并不适合贪心策略。 接下来我们把问题分解,假如知道从顶点到每个点的最优解的话,最终答案也就能够得出了。假设第i行第j个元素为止的最优解为f[i][j],可以想到f[i][j]只和f[i-1][j]和f[i-1][j-1](如果存在的话)有关。也就是说第i行的解只会跟第i-1行的一个或两个元素有关。
代码:
#include <iostream> #include <cstdio> using namespace std; const int N = 100; // 下面这个函数实现的是更新最大值,o赋值为o和x的最大值 template <class T> void updateMax(T& o, const T& x) { o = (o > x) ? o : x; } // f数组为动态规划的状态数组 // num数组为读入的数塔 // n为读入的数塔高度 int f , num , n; int main() { // 读入n和数塔数组num scanf("%d", &n); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= i; ++j) { scanf("%d", &num[i][j]); } } // step 1 begin: 在这里实现动态规划算法逻辑 for (int i=1;i<=n;++i){ for(int j=1;j<=i;++j){ updateMax(f[i][j],max(f[i-1][j],f[i-1][j-1])+num[i][j]); } } // step 1 end. // 定义最终结果变量result,因为是计算最大值,所以初始化为0 int result = 0; for (int i = 1; i <= n; ++i) { // step 2 begin: 在这里实现更新最终结果的逻辑 updateMax(result,f [i]); // step 2 end. } // 输出最终最大权值和result printf("%d\n", result); return 0; }
相关文章推荐
- 建造者模式
- Android学习一(windows安装Git)
- 蓝牙模块
- 第四章 流程控制与数组
- PHP IDE phpstorm 常用快捷键
- 入CTF坑必不可少的地方-保持更新
- Android DownloadManager 的使用
- css3图片添加阴影
- hdoj 1286 找新朋友<欧拉函数>
- git时认证失败(Authentication failed )的解决
- 安卓向服务器发送数据和服务器接收数据全过程
- 基于jQuery.validate及Bootstrap的tooltip开发气泡样式的表单校验组件思路详解
- python爬虫之豆瓣图书信息几行字
- 一个书页卷角的HTML&CSS效果
- 8B - Obsession with Robots
- 【杭电oj】1715 - 大菲波数(大数递推)
- BestCoder 2nd Anniversary--1001Oracle
- ASP.NET MVC对WebAPI接口操作(添加,更新和删除)
- UIALertView的基本用法与UIAlertViewDelegate对对话框的事件处理方法
- 2016.07.17【初中部 NOIP提高组 】模拟赛C(附题目及代码打包)