UVA 10891

来源:互联网 发布:数据库遍历.zip 编辑:程序博客网 时间:2024/06/05 09:53

dp[i][j]-> 从I 到J 的 最大差值

sum[i] 前I 项和;

  经典DP 模型变形

       如果不是连续的选(只从某一端选一个)的话 dp[i][j] = sum[j] - sum[ i -1] - min( dp[i] [j - 1] , dp[i+1] [j]) ;

       随意连续的话就是枚举i~j内每一个dp[i][k] ( 注意要从两个方向)

      还需要注意的是如果我用这种最有策略得出的结果没有区间和大,由于我可以任意选择我想要取得区间长度所以 此时 dp[j][i-1] = sum[j] - sum[i-1];

#include <iostream>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>


using namespace std;
#define MAXN 110
#define INF 10000000
int dp[MAXN][MAXN];
int sum[MAXN];
int sto[MAXN];
int main()
{
    int n;
    while(scanf("%d",&n) != EOF && n)
    {
         sum[0] = 0;
         memset(dp, -INF ,sizeof(dp));
        for( int i = 1; i <= n; i++)
         {
             scanf("%d",&sto[i]);
             sum[i] = sum[i-1] + sto[i];
             dp[i][i] = sto[i];
         }


         for( int k = 1; k < n; k++)
         {
             for( int i = 1; i + k <= n; i++)
             {
                 int j = i + k;
                 int res = sum[j] - sum[i-1];


                 int minn = INF;
                 for( int l = i; l < j; l++)
                   minn = min( minn, dp[i][l]);


                 for( int l = i + 1; l <= j; l++)
                   minn = min(minn, dp[l][j]);


                dp[i][j] = res - minn;
                if(res > dp[i][j])
                 dp[i][j] = res;
             }
         }


         printf("%d\n", 2 * dp[1][n] - sum[n]);
    }
    return 0;
}
0 0
原创粉丝点击