Another OCD Patient
http://acm.hdu.edu.cn/showproblem.php?pid=4960
Problem Description
Xiaoji is an OCD (obsessive-compulsive disorder) patient. This morning, his children played with plasticene. They broke the plasticene into N pieces, and put them in a line. Each piece has a volume Vi. Since Xiaoji is an OCD patient, he can't stand with the disorder of the volume of the N pieces of plasticene. Now he wants to merge some successive pieces so that the volume in line is symmetrical! For example, (10, 20, 20, 10), (4,1,4) and (2) are symmetrical but (3,1,2), (3, 1, 1) and (1, 2, 1, 2) are not.
However, because Xiaoji's OCD is more and more serious, now he has a strange opinion that merging i successive pieces into one will cost ai. And he wants to achieve his goal with minimum cost. Can you help him?
By the way, if one piece is merged by Xiaoji, he would not use it to merge again. Don't ask why. You should know Xiaoji has an OCD.
However, because Xiaoji's OCD is more and more serious, now he has a strange opinion that merging i successive pieces into one will cost ai. And he wants to achieve his goal with minimum cost. Can you help him?
By the way, if one piece is merged by Xiaoji, he would not use it to merge again. Don't ask why. You should know Xiaoji has an OCD.
Input
The input contains multiple test cases.
The first line of each case is an integer N (0 < N <= 5000), indicating the number of pieces in a line. The second line contains N integers Vi, volume of each piece (0 < Vi <=10^9). The third line contains N integers ai (0 < ai <=10000), and a1 is always 0.
The input is terminated by N = 0.
The first line of each case is an integer N (0 < N <= 5000), indicating the number of pieces in a line. The second line contains N integers Vi, volume of each piece (0 < Vi <=10^9). The third line contains N integers ai (0 < ai <=10000), and a1 is always 0.
The input is terminated by N = 0.
Output
Output one line containing the minimum cost of all operations Xiaoji needs.
Sample Input
5 6 2 8 7 1 0 5 2 10 20 0
Sample Output
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.
题目大意:一个含有n个数点序列,可以合并任意i个连续点数,花费为a[i],寻找最终结果序列是回文时点最小花费
这个题只要想到抓住前缀和与后缀和相等的点进行dp就很容易了(依旧想不到。。。)
首先找出所有点i对称点opp[i](区间不相交),对称点的初值为:dp[i]=a[i]+a[n-opp[i]+1],然后再通过i前面点对称点j对其进行更新
最后注意对称点间点区间[i,opp[i]]也可以进行合并
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=5005;
int n,num;
int v[MAXN],a[MAXN],opp[MAXN];
long long prefix[MAXN],suffix[MAXN],dp[MAXN],ans;
int main() {
freopen("in.txt","r",stdin);
while(scanf("%d",&n),n!=0) {
prefix[0]=suffix[0]=suffix[n+1]=0;
for(int i=1;i<=n;++i) {
scanf("%d",v+i);
prefix[i]=prefix[i-1]+v[i];//计算v的前缀和
}
for(int i=n;i>0;--i) {
scanf("%d",a+n-i+1);
suffix[i]=suffix[i+1]+v[i];//计算v的后缀和
}
int il=1,ir=n;
while(il<=n) {//寻找对称点
while(ir>0&&prefix[il]>suffix[ir])
--ir;
opp[il]=(prefix[il]==suffix[ir]?ir:0);
++il;
}
memset(dp,0x3f,sizeof(dp));
for(int i=1;i<=n;++i) {
if(opp[i]!=0&&i<opp[i]) {//当i点是对称点且两个区间没有相交部分
dp[i]=a[i]+a[n-opp[i]+1];//初始化dp[i]为区间[1,i]、区间[opp[i],n]合并
for(int j=1;j<i;++j) {
if(opp[j]!=0)
dp[i]=min(dp[i],dp[j]+a[i-j]+a[opp[j]-opp[i]]);
}
}
}
ans=a[n];//初始区间[1,n]全部合成一个数字
for(int i=1;i<=n;++i)
if(i<opp[i])//区间[i+1,opp[i]-1]合成一个数字
ans=min(ans,dp[i]+a[opp[i]-i-1]);
printf("%I64d\n",ans);
}
return 0;
}