标签:des style blog http color os java io strong
题目大意:给你一串数字让你判断经过若干次合并,使得这个数字串变成回文串的最小成本是多少。第一行是数字串,第二行是合并连续i个数字的成本是多少。
解题思路:区间dp,可以进行记忆化搜索,如果左边比右边和大那么右边一定是小了,右边比左边大那么左边一定小了。因为保证有解。具体不太好说,直接看代码吧。
5 6 2 8 7 1 0 5 2 10 20 0
10HintIn the sample, there is two ways to achieve Xiaoji‘s goal. [6 2 8 7 1] -> [8 8 7 1] -> [8 8 8] will cost 5 + 5 = 10. [6 2 8 7 1] -> [24] will cost 20.
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-10
///#define M 1000100
///#define LL __int64
#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?0:x)
using namespace std;
const int maxn = 5010;
int dp[maxn][maxn];
LL sum[maxn];
int num[maxn];
int dfs(int l, int r)
{
    if(l > r) return 0;
    if(dp[l][r] != -1) return dp[l][r];
    dp[l][r] = num[r-l+1];
    int ll = l, rr = r;
    while(ll < rr)
    {
        if((sum[ll]-sum[l-1]) > (sum[r]-sum[rr-1])) rr--;
        else if((sum[ll]-sum[l-1]) < (sum[r]-sum[rr-1])) ll++;
        else if((sum[ll]-sum[l-1]) == (sum[r]-sum[rr-1]))
        {
            dp[l][r] = min(dp[l][r], num[ll-l+1]+dfs(ll+1, rr-1)+num[r-rr+1]);
            rr--;
        }
    }
    return dp[l][r];
}
int main()
{
    int n;
    while(~scanf("%d",&n) && n)
    {
        sum[0] = 0;
        for(int i = 0; i <= n; i++)
            for(int j = 0; j <= n; j++) dp[i][j] = -1;
        LL x;
        for(int i = 1; i <= n; i++)
        {
            scanf("%I64d",&x);
            sum[i] = sum[i-1]+x;
        }
        for(int i = 1; i <= n; i++) scanf("%d",&num[i]);
        cout<<dfs(1, n)<<endl;
    }
    return 0;
}
HDU 4960 Another OCD Patient(区间dp记忆化搜索)
标签:des style blog http color os java io strong
原文地址:http://blog.csdn.net/xu12110501127/article/details/38853273