[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\n",ans); } return 0; }