HDU 4960 Another OCD Patient(DP)
来源:互联网 发布:java的mvc框架 编辑:程序博客网 时间:2024/05/17 02:53
题意就是给你5000个数字,然后还有合并i个数字所需要的花费,然后每个数字只能合并1次,要把这串数字通过合并成为对称的数字,问你最小花费。
做法:用2个数组去分别保存从左往右以及从右往左对称的地方的长度,也就是比如1 3 4 3 1 2 2 ,b[0] = 2,b[1] = 1,c[0] = 1, c[1] = 2。
在预处理过后,数字就变得没有用了,有用的就是这2个数组,但是这里会出现一个情况就是中间某一段不能匹配成为相等的,也就是说必须要合并成1个数。
假设有k个匹配的段,dp[i]等于min{ 2个数组的 i 到 k 的数字全部合并一起的花费加上dp[k]}。这里推完后dp[k-1]加上前面说的中间那段不能匹配的花费就是解了。
等一下,这样并不对。因为可能最优解是中间那段加上左右2段匹配的合在一起再加上dp得到的。所以还需要推一遍,从中间开始推,ans = min{中间那段加上左右2段的数字个数合起来的花费加上dp[i]}。这点很容易想不到。
AC代码:
#include<cstdio>#include<ctype.h>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdlib>#include<stack>#include<cmath>#include<queue>#include<set>#include<ctime>#include<string.h>#include<string>using namespace std;#define ll __int64#define eps 1e-8ll a[5005];int cost[5005];int b[5005],c[5005];ll dp[5005];template<class T>inline void scan_d(T &ret) { char c; ret=0; while((c=getchar())<'0'||c>'9'); while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); } int main(){ #ifdef GLQ freopen("input.txt","r",stdin);// freopen("o.txt","w",stdout); #endif // GLQ int n,i,j; while(~scanf("%d",&n)&&n) { for(i = 0; i < n; i++) scan_d(a[i]); for(i = 1; i <= n; i++) scan_d(cost[i]); i = 1;j = n-2; int k = 0,nct1=1,nct2=1; ll t1 = a[0], t2 = a[n-1]; int oldi=0,oldj=n-1,flag = 0; while(1) { if(t1 > t2) { t2 += a[j--]; nct2++; } else if(t2 > t1) { t1 += a[i++]; nct1++; } else if(t2 == t1) { b[k] = nct1; c[k++] = nct2; nct1=nct2=1; oldi = i; oldj = j; if(i==j+1) break; t1=a[i++]; t2=a[j--]; } if(j < i-1) { flag = 1; break; } } ll jia=0; if(flag) jia = cost[oldj-oldi+1]; memset(dp,0,sizeof(dp));// for(i = 0; i < k; i++) cout<<b[i]<<" "<<c[i]<<endl; int temp1=0,temp2=0; for(i = 0; i < k; i++) { dp[i] = (ll)cost[temp1+b[i]]+(ll)cost[temp2+c[i]]; temp1 = b[i]; temp2 = c[i]; for(j = i-1; j >= 0; j--) { dp[i] = min(dp[i],(ll)cost[temp1]+(ll)cost[temp2]+dp[j]); temp1 += b[j]; temp2 += c[j]; }// cout<<temp1<<" "<<temp2<<endl;// cout<<dp[i]<<endl; } ll ans = min(dp[k-1]+(ll)jia,(ll)cost[n]); if(k == 0) { printf("%d\n",cost[n]); continue; } int w1 = 0,w2 = 0; for(i = k-1; i >= 0; i--) { ans = min(ans,dp[i]+(ll)cost[oldj-oldi+1+w1+w2]); w1 += b[i]; w2 += c[i]; } printf("%I64d\n",ans); } return 0;}
0 0
- HDU 4960 Another OCD Patient(DP)
- HDU-4960 Another OCD Patient (DP)
- hdu 4960 Another OCD Patient(DP)
- 【HDU】4960 Another OCD Patient 【DP】
- HDU 4960 Another OCD Patient 区间dp
- hdu 4960 Another OCD Patient dp
- HDU 4960(Another OCD Patient-区间dp)
- HDU 4960 Another OCD Patient (dp)
- hdu 4960 Another OCD Patient dp(记忆化搜索)
- hdu 4960 Another OCD Patient dp(记忆化搜索)
- hdu 4960 Another OCD Patient
- HDU 4960 Another OCD Patient
- HDU 4960 Another OCD Patient
- hdu 4960 Another OCD Patient 多校九 区间DP
- HDU 4960 Another OCD Patient(区间dp记忆化搜索)
- Another OCD Patient HDU
- 【DP】 HDOJ 4960 Another OCD Patient
- hdu 4960 Another OCD Patient(dp)2014多校训练第9场
- hdu4973
- POJ 1459 Power Network
- Ubuntu上编译安装Freetype/Freetype-py
- 韩语学习之第十一课
- svn代码回滚命令
- HDU 4960 Another OCD Patient(DP)
- Candy
- MySQL 数据类型
- HDU 3549 Flow Problem
- 基于OpenCV依次读取文件夹下的所有图像文件
- 数字对象
- JAVA多线程变量的深入认识(三)
- 《C++ Primer》阅读笔记1
- 嵌入式开发技术三级