【HDU4960】Another OCD Patient
题意
给出一个长度为n的整数序列。可以将一段连续的序列进行合并。合并的长度不同代价不同。问付出最少多少代价可以将这个序列变成一个对称的序列。n<=5000
分析
一看题感觉是个dp很好写啊。f[i][j]为令区间[i,j]对称的最小花费。那么转移并不难想
f[i][j]=min(f[i][j],f[i+l1][j-l2]+val[l1-i+1]+val[j-l2+1] | sum[l1]-sum[i-1]==sum[j]-sum[l2-1]);
然后按照区间dp的写法就写了一个迭代然后T掉了。看了一下这样好像是n^3的?下面是T的代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int MAX = +;
int dp[MAX][MAX],a[MAX],v[MAX];
LL sum[MAX];
int dfs(int L,int R) {
if(L>=R) return ;
if(~dp[L][R]) return dp[L][R];
LL sum1,sum2; int ans=a[R-L+];
for(int i=L,j=R;i<j;) {
sum1=sum[i]-sum[L-];
sum2=sum[R]-sum[j-];
if(sum1==sum2) {
ans=min(ans,dfs(i+,j-)+a[i-L+]+a[R-j+]);
i++; j--;
}
else if(sum1>sum2) j--;
else i++;
}
return dp[L][R]=ans;
}
int main() {
int n;
while(scanf("%d",&n)==&&n) {
memset(sum,,sizeof(sum));
for(int i=;i<=n;i++) {
scanf("%d",&v[i]);
sum[i]=sum[i-]+v[i];
}
for(int i=;i<=n;i++) {
scanf("%d",&a[i]);
}
memset(dp,-,sizeof(dp));
int ans=dfs(,n);
printf("%d\n",ans);
}
然后我去网上查了一下,发现这个思想用记忆搜索可以过。。。emmm想一下,貌似是啊,记忆搜索是n^2logn?下面是记忆搜索的代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream> using namespace std;
const int maxn=+;
const int INF=;
int a[maxn],val[maxn],f[maxn][maxn];
int n;
long long sum[maxn];
int dfs(int L,int R){
if(f[L][R]!=-)
return f[L][R];
f[L][R]=val[R-L+];
for(int i=L,j=R;i<j;){
long long sum1=sum[i]-sum[L-];
long long sum2=sum[R]-sum[j-];
if(sum1==sum2){
f[L][R]=min(f[L][R],dfs(i+,j-)+val[i-L+]+val[R-j+]);
i++,j--;
}
else if(sum1>sum2)j--;
else i++;
}
return f[L][R];
}
int main(){
while(scanf("%d",&n)!=EOF&&n){
sum[]=;
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-]+a[i];
}
for(int i=;i<=n;i++)
scanf("%d",&val[i]);
memset(f,-,sizeof(f));
int ans=dfs(,n);
printf("%d\n",ans);
}
return ;
}
然后又开始想迭代该怎么写···
先按照上面的方法预处理出一个pos[maxn]数组,j=pos[i],sum[i]=sum[n]-sum[j-1]。也就是说1-i的和等于pos[i]到n的和。
设一个dp数组f[i]为将1-i和将pos[i]到n合并的最小花费是多少。
转移:f[i]=min(f[i],f[j]+val[i-j]+val[pos[j]-pos[i]])
最终答案是 ans=min(f[i]+val[pos[i]-i-1]);
恩,就是这样。下面是AC代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream> using namespace std;
const int INF=;
const int maxn=+;
int a[maxn],val[maxn],f[maxn],pos[maxn];
long long sum[maxn]; int n;
int main(){
while(scanf("%d",&n)!=EOF&&n){
sum[]=;
memset(pos,,sizeof(pos));
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-]+a[i];
}
for(int i=;i<=n;i++)
scanf("%d",&val[i]);
int i=,j=n;
while(i<j){
long long sum1=sum[i];
long long sum2=sum[n]-sum[j-];
if(sum1==sum2){
pos[i]=j;
i++,j--;
}
else if(sum1<sum2)i++;
else j--;
}
memset(f,,sizeof(f));
/*for(int i=1;i<=n;i++){
printf("%d ",pos[i]);
}*/
f[]=val[n];
for(int i=;i<=n;i++){
if(!pos[i])continue;
f[i]=val[i]+val[n-pos[i]+];
for(int j=;j<i;j++){
if(pos[j]!=){
f[i]=min(f[i],f[j]+val[i-j]+val[pos[j]-pos[i]]);
}
}
}
int ans=val[n]; for(int i=;i<=n;i++)
if(pos[i]||i==){
if(pos[i]>i+)
ans=min(ans,f[i]+val[pos[i]-i-]);
else
ans=min(ans,f[i]);
}
printf("%d\n",ans); /* for(int i=0;i<=n;i++)
printf("%d %d %d\n",i,pos[i],f[i]);*/
}
return ;
}
【HDU4960】Another OCD Patient的更多相关文章
- 【转载】如何破解受保护的excel密码
[工具] 1.电脑一台(安装有Microsoft Excel) 2.受保护excel一个 [步骤] 1.首先,打开受保护的Excel表格,按"ALT"+"F11" ...
- 【Java】-NO.20.Exam.1.Java.1.001- 【1z0-807】- OCEA
1.0.0 Summary Tittle:[Java]-NO.20.Exam.1.Java.1.001-[1z0-807] Style:EBook Series:Java Since:2017-10- ...
- Python高手之路【六】python基础之字符串格式化
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...
- 【原】谈谈对Objective-C中代理模式的误解
[原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【调侃】IOC前世今生
前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...
- Python高手之路【三】python基础之函数
基本数据类型补充: set 是一个无序且不重复的元素集合 class set(object): """ set() -> new empty set object ...
- Python高手之路【一】初识python
Python简介 1:Python的创始人 Python (英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种解释型.面向对象.动态数据类型的高级程序设计语言,由荷兰人Guido ...
随机推荐
- Leetcode 1020. Number of Enclaves
dfs或者bfs class Solution: def dfs(self, A, rows, cols, i, j): if not (0 <= i < rows and 0 <= ...
- MySql 批量创建、导入实例
1.创建sql(例如,taobao,dangdang): DROP DATABASE IF EXISTS taobao; CREATE DATABASE taobao CHARSET=utf8; US ...
- apply 无循环拼接数组
apply()第二个参数只能是数组,这个数组将作为参数传给原函数的参数列表arguments. 其实在实际开发中,JS 继承的方法并不止这一种,使用原型链继承是更加常用的方式,此外还有构造函数继承,这 ...
- description方法
1.NSLog回顾 众所周知,我们可以用NSLog函数来输出字符串和一些基本数据类 1 int age = 11; 2 NSLog(@"age is %i", age); * 第2 ...
- SQLserver2008使用表达式递归查询
--由父项递归下级 with cte(id,parentid,text) as ( --父项 select id,parentid,text from treeview where parentid ...
- js删除局部变量的实现方法
lert('value:'+str+'\ttype:'+typeof(str)) //声明变量前,引用 var str="dd"; alert('value:'+str+'\tty ...
- 学习动态性能表(4)--v$sqltext&v$sqlarea
学习动态性能表 第四篇-(1)-V$SQLTEXT 2007.5.29 本视图包括Shared pool中SQL语句的完整文本,一条SQL语句可能分成多个块被保存于多个记录内. 注:V$SQLARE ...
- (转)用Eclipse 统计代码行数小技巧
今天公司SQA问我目前项目代码行数有多少,我当时就是想,以前好像写过类似的统计工具但是一时又找不到 公司网络又不能下载,所以想想eclipse是不是又类似功能,找了下没有,但突然一想有一个转弯方法:统 ...
- 如何注册java程序为windows服务
如何注册java 程序为windows 服务 最近想找个软件来控制电脑的关机时间,在网上找了几个,都是可视化界面的可以设置具体的关机时间的软件.由于我想编写的关机程序是运行在别人机器上,只能让该机器在 ...
- onItemLongClick事件的监听
首先需要implements public class MainActivity extends AppCompatActivity implements OnItemLongClickListene ...