【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 ...
随机推荐
- CSS3盒模型display:box简述
display:box;box-flex是css3新添加的盒子模型属性,它的出现可以解决我们通过N多结构.css实现的布局方式.经典的一个布局应用就是布局的垂直等高.水平均分.按比例划分. box-f ...
- vs无法调试 ,还没有为该文档加载任何符号
如何:启用非托管代码调试 位于“项目设计器”的“调试”页上的“非托管代码调试”属性确定是否支持本机代码调试. 如果要调用 COM 对象,或启动调用您的项目的.以本机代码编写的自定义程序,并且需要调 ...
- Helix Server流媒体服务器架设教程(附Helix Server11.01下载)
现在D版的远古影视系统很流行,也很实用,但是在这之前,很多人都是用共享,或者是使用Helix Server留媒体来做电影服务器~ 虽然Helix Server流媒体服有点落伍了,不过我相信它还是有用武 ...
- python 中出现 “IndentationError: expected an indented block” 问题
python 学习 在定义Python函数的时候如下 >>>def hello() . . .print "hello" 这样会报错的,报错如下: Indenta ...
- 处理SQL Server 异常常用步骤
处理SQL Server 异常常用步骤 SQL Server常见的问题主要是SQL问题造成,常见的主要是CPU过高和阻塞. 一.CPU过高的问题 1.查询系统动态视图查询执行时间长的sql语句 WIT ...
- Chrome 的书签太多如何分类整理比较好
对于Chrome书签太多,如何进行分类整理,下面给出几种方法~ 工具/原料 电脑 Chrome浏览器 delicious.Diigo等 方法/步骤1 1.把书签中常用网站只保存LOGO,放在书签栏最前 ...
- 解决Net内存泄露原因
Net内存泄露原因及解决办法 https://blog.csdn.net/changtianshuiyue/article/details/52443821 什么是.Net内存泄露 (1).NET 应 ...
- 配置linux下面python的开发环境
1.首先安装Python开发环境 http://blog.csdn.net/testcs_dn/article/details/51253365 2.安装django开发环境 http://blog. ...
- Free Online SQL Formatter
SQL Formatter Web Service Free Online SQL Formatter SQL Parser engine used by SQL formatter 今日找了几个在线 ...
- 谷歌(google)世界各国网址大全
谷歌(google)世界各国网址大全世界各国google网址 国家 网址 国家主要语言 亚洲:中国 google.cn 汉语蒙古 google.mn蒙古语韩国 google.c ...