【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 ...
随机推荐
- Unity在协程(Coroutines)内开启线程(Threading )
孙广东 2017.6.13 http://blog.csdn.NET/u010019717 为什么要在协程中开启线程, 因为很多时候我们是需要线程执行完成后回到主线程的.然后主线程在继续执行后续的操 ...
- C高级第一次作业附加
之前的作业链接:http://www.cnblogs.com/1204113692yang/p/8625650.html 过去两周学习了指针的概念.指针变量的定义.指针的基本运算.指针操作改变主调函数 ...
- MYSQL 重新设置自增值
说明:当一张有auto_increment主键的表中存有10条数据,现删除5-10条数据, 再insert数据的时候auto_increment将从11开始. 现在我们改变它设为从6开始. ALTER ...
- Sphinx 匹配模式
所谓匹配模式就是用户如何根据关键字在索引库中查找相关的记录. SPH_MATCH_ALL, 匹配所有查询分词(默认模式); 如“手机配件”,不匹配 “我有一部手机”,但可以匹配 “手机坏了,需要找配件 ...
- 【数据库】SQLite学习
http://www.cnblogs.com/fnng/archive/2013/05/26/3099547.html
- web应用程序安全攻防---sql注入和xss跨站脚本攻击
kali视频学习请看 http://www.cnblogs.com/lidong20179210/p/8909569.html 博文主要内容包括两种常见的web攻击 sql注入 XSS跨站脚本攻击 代 ...
- self = [super init]
Objective-C的推荐init方法写法如下: - (id) init { if(self = [super init]) { //为子类增加属性进行初始化 } return self; } 返回 ...
- verilog 2001中的一些新语法
比较有用的:1,generate语句,但需注意,generate-for中变量范围是已知的确定值, generate-case,generate-if语句中变量都必须是固定的, generate必须跟 ...
- jfrog artifactory jenkins pipeline 集成
1. 预备环境 artifactory ( 开源版本 ) maven jenkins jenkins artifactory plugin (在插件管理安装即可) 2. 配置artifactory ...
- HttpModule和HttpHandler -- 系列文章
ASP.NET 生命周期 在ASP.Net2.0中使用UrlRewritingNet实现链接重写 IHttpModule实现URL重写 使用IHttpHandler防盗链 HttpModule,Htt ...