动态规划法.md
2015-05-29 19:01
197 查看
动态规划算法
动态规划算法通常基于一个递推公式及一个或多个初始状态。当前子问题的解决将由上一次子问题的解推出。例题:
http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1017
题中所述的是在长度为N数字串中,添加K个乘号,将它分成K+1个部分,使得这K+1个部分的乘积最大
- 1.状态及状态转移方程(根据子问题定义状态)
首先要定义一个“状态”来代表它的子问题,并且找到它的解。分解出子问题:把前i个数字分成j部分,计算最大值。我们用sum[i][j]表示从第i位到第j位组成的数字;f[i][j]表示把前i个数字分成j份乘积的最大值,要求出j个部分的乘积最大值,再次分解子问题:把前k个数字分成j-1个部分(1<=k<=i-1),可以得出状态转移方程:f[i][j]=max(f[i][j],f[k][j-1]*sum[k+1][i]);(建议自己动手画一下0~n简图,容易理解一些)
- 2.附加条件
需要根据实际情况考虑到可能存在的附加条件
例题中一定会有f[i][0]==sum[1][i];(1<=x<=N)
- 3.时间复杂度
根据程序实现,分析时间复杂度,本例:O(N^2*K)
总结:找到状态是关键,由此推出状态转移方程。学会将大规模问题分解为子问题,根据子问题定义状态
源码:
[code]#include<iostream> #include<stdlib.h> #include<string.h> using namespace std; long long f[41][7]; long long sum[41][41]; char str[42]; #define max(a,b) (a>b? (a):(b)) int main() { int i, j; int n, k; cin >> n >> k; for ( i = 1; i <= n; i++) { cin >> str[i]; } for (i = 1; i <=n; i++) { for (j = i; j <= n; j++) { sum[i][j] = sum[i][j - 1] * 10 + str[j] - '0';//sum[i][j]代表第i位数到第j位数组成的数字 } } for (i = 1; i <= n; i++) { f[i][0] = sum[1][i];// f[i][j]代表把前i个数字分成j份乘积的最大值,j个乘号 } for (j = 1; j <= k; j++) { for (i = 2; i <= n; i++) { for (int k = 1; k < i; k++) f[i][j] = max(f[i][j], f[k][j - 1] * sum[k + 1][i]); } } cout << f [k]; system("pause"); return 0; }
附:
最长坡之问题http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1031
相关文章推荐
- 建造者模式
- 构建之法-8.9.10
- 设计模式
- hdu3932 模拟退火
- Android 常用 adb 命令总结
- html中的meta
- JavaScript自学第4讲:JavaScript运算符介绍
- 在java中生成二维码,并直接输出到jsp页面
- Maven入门指南⑤:使用Nexus搭建Maven私服
- 转载:你还在用jquery.lazyload这个坑爹的图片分屏加载插件么?
- 2.3-7
- const 修饰函数
- Java利用Zxing生成二维码
- HDU 1481 树的性质(神坑)
- 使用MySQL图形化工具Navicat创建表
- machine learning (7)---normal equation相对于gradient descent而言求解linear regression问题的另一种方式
- 《构建之法》8、9、10
- 读8,9,10 章感悟
- 2.3-6
- 面试题10:求二进制中1的个数