初入DP
动态规划(DP): 主要用于组合优化问题,即求一个离散问题在某种意义上的最优解。
适合用动态规划的两个基本要素:
》最优子结构性质(该问题的最优解包含子问题的最优解)
》子问题重叠性(当前所对应的子问题呈现大量的重复)
动态规划的算法步骤:
》选择适当的问题状态表示, 分析最优解的性质。
》建立递归关系(定义最优值)。
》以自底向上的方法计算最优值。
》根据计算最优值时得到的信息,构造一个最优解。
注意: 》要充分利用子问题的重叠性来提高解题效率。采用迭代的方法计算最优值而不是直接递归。
》 最大子序列
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1003
题意: 一组数据,求其连续子序列和值最大为多少,并记录其子序列的开始下标和结束下标
#include <iostream> #include <cstdio> #define Min -100000005 using namespace std; int main() { int t, ti, i, a, n; scanf("%d", &t); for(ti=1; ti<=t; ti++) { int head=1, head1=1, last=1, sum=0, finmax=Min; scanf("%d", &n); for(i=1; i<=n; i++) { scanf("%d", &a); sum+=a; //sum记录连续加和的值 if(sum>finmax) //如果sum大于最大值(finmax) { head = head1; //更新现在的finmax和finmax的开始下标,结束下标, last=i; finmax=sum; } if(sum<0) //如果sum小于0 则更新暂时的头结点(head1) { head1=i+1; sum=0; //sum归零重新加和 } } printf("Case %d:\n%d %d %d\n", ti, finmax, head, last); if(ti<t) puts(""); } return 0; }
》 最大子矩阵
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1081
题意:给你一个n*n的矩阵,让你求出其子矩阵中各个元素的和最大值。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int s[105][105]; int dp[105]; int n; int Maxsum( ) { int sum=0, max=-100000, i; for(i=1; i<=n; i++) //最大子串问题 { sum += dp[i]; if(sum > max) max=sum; if(sum < 0) sum=0; } return max; } int main() { while(scanf("%d", &n)!=EOF) { int t, i, j, max, finmax; for(i=1; i<=n; i++) for(j=1; j<=n; j++) scanf("%d", &s[i][j]); finmax=0; for(t=1; t<=n; t++) //控制搜索行数 { memset(dp, 0, sizeof(dp)); for(i=t; i<=n; i++) // 行数 { for(j=1; j<=n; j++) //列数 dp[j] += s[i][j]; //计算[1,j]列的和值 max = Maxsum( ); //寻找矩阵[t, n]行的最大值 if(max > finmax) finmax=max; } } printf("%d\n", finmax); } return 0; }

浙公网安备 33010602011771号