初入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;
}

 

  

posted @ 2015-09-21 22:08  马晨  阅读(75)  评论(0)    收藏  举报