[hdu4960]Another OCD Patient(区间dp)

题意:给出n个数,把这n个数合成一个对称的集合。每个数只能合并一次。

解题关键:区间dp,dp[l][r]表示l-r区间内满足条件的最大值。vi是大于0的,所以可以直接双指针确定。

转移方程:$dp[l][r] = min (val(r - l + 1),val(r - i + 1) + val(j - l + 1) + dp[j + 1][i - 1])$

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int dp[5002][5002],v[5002],a[5002];
ll sum[5002];
ll dfs(ll L,ll R){
    if(L>=R) return 0;
    if(~dp[L][R]) return dp[L][R];
    ll ans=a[R-L+1],l=L,r=R;
    while(l<r){
        ll sum1=sum[l]-sum[L-1],sum2=sum[R]-sum[r-1];
        if(sum1==sum2){
            ans=min(ans,dfs(l+1,r-1)+a[l-L+1]+a[R-r+1]);
            l++,r--;
        }else if(sum1<sum2) l++;
        else r--;
    }
    return dp[L][R]=ans;
}
int main(){
    ll n;
    while(~scanf("%lld",&n)&&n){
        for(int i=1;i<=n;i++) scanf("%d",v+i),sum[i]=sum[i-1]+v[i];
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        memset(dp,-1,sizeof dp);
        ll ans=dfs(1,n);
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/elpsycongroo/p/7804941.html