HDU 4960 (区间DP)
2016-06-27 10:05
405 查看
题目链接:点击这里
题意:把一个数列合并成回文序列,每一个数字只能和并一次,只能连续的子串进行合并,合并后的数字是他们的和,花费是他们中数字个数的函数。给出原始串和花费函数求最小的花费。
O(n)扫一遍相等的前缀的后缀,dpi表示i下标和对应下标的后缀合并之后的最小花费,那么dpi=min{dpj+cost(i,j−1)∥∥i≤j}
#include <bits/stdc++.h> using namespace std; #define maxn 5005 int n; int a[maxn]; int v[maxn]; int x[maxn], y[maxn]; long long dp[maxn]; long long sumx[maxn]; long long sumy[maxn]; int main () { //freopen("1.txt","r",stdin); while(scanf("%d",&n)&&(n!=0)) { sumx[0] = 0, sumy[n+1] = 0; for (int i = 1; i <= n; i++) scanf("%d", &a[i]), sumx[i] = sumx[i-1]+a[i]; for (int i = n; i >= 1; i--) sumy[i] = sumy[i+1]+a[i]; for (int i = 1; i <= n; i++) scanf ("%d", &v[i]); int L = 1, R = n, tt = 0; while (L <= R+1) { if (sumx[L-1] == sumy[R+1]) { x[++tt] = L, y[tt] = R; L++, R--; } while (L <= R+1 && sumx[L-1] < sumy[R+1]) L++; while (L <= R+1 && sumx[L-1] > sumy[R+1]) R--; } for (int i = tt; i >= 1; i--) { dp[i] = v[y[i]-x[i]+1]; //不断开 for (int j = i+1; j <= tt; j++) { int num_l = x[j]-x[i], num_r = y[i]-y[j]; dp[i] = min (dp[i], dp[j]+v[num_l]+v[num_r]); } } printf ("%lld\n", dp[1]); } return 0; }
相关文章推荐
- 浏览器阻止新窗口(window.open或新窗的form提交)
- 对MTK平台的一些认识
- input框限制只能输入正整数、字母、小数、汉字
- 使用DotNetBarcode制作基本常用条码
- 当xcode里点运行出现treating unicode character as whites
- 一些小函数
- LINUX-vbird
- Java基础之异常Exception(5)---小练习
- 前端同学大福利,最全的面试题目整理
- MFC-控件-标签-设置背景透明
- 敏捷测试模式之Scrum及其实践
- Java中的拆箱和装箱
- iOS 纯代码控件布局
- timeout connect 10000 # default 10 second time out if a backend is not found
- MyEclipse + Maven开发Web工程的详细配置过程
- 解析ABP框架中的数据传输对象与应用服务
- 统计字符串中重复的字符个数及字符
- timeout connect 10000 # default 10 second time out if a backend is not found
- timeout connect 10000 # default 10 second time out if a backend is not found
- Python3内置函数实例解析