题意

给出一个长度为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的更多相关文章

  1. 【转载】如何破解受保护的excel密码

    [工具] 1.电脑一台(安装有Microsoft Excel) 2.受保护excel一个 [步骤] 1.首先,打开受保护的Excel表格,按"ALT"+"F11" ...

  2. 【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- ...

  3. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  4. 【原】谈谈对Objective-C中代理模式的误解

    [原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...

  5. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  6. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  7. 【调侃】IOC前世今生

    前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...

  8. Python高手之路【三】python基础之函数

    基本数据类型补充: set 是一个无序且不重复的元素集合 class set(object): """ set() -> new empty set object ...

  9. Python高手之路【一】初识python

    Python简介 1:Python的创始人 Python (英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种解释型.面向对象.动态数据类型的高级程序设计语言,由荷兰人Guido ...

随机推荐

  1. mysql的5.6版本支持分区吗?

    转载请注明出处:http://blog.csdn.net/dongdong9223/article/details/72291698 本文出自[我是干勾鱼的博客] 我们知道,查看mysql是否支持分区 ...

  2. Android数据库代码优化(2) - 从SQLite说起

    从SQLite说起 如果没有SQLite的基础,我们只是从Android封装的SQLite API去学习的话,难免思路会受到限制.所以,我们还是需要老老实实从头开始学习SQLite. 当我们有一身的S ...

  3. (转) Myisam和Innodb索引实现的不同(存储结构)

    转自 :  https://blog.csdn.net/donghaixiaolongwang/article/details/60751543

  4. 人生苦短之我用Python篇(安装第三方库、正则表达式)

    安装第三方库 两种方法, 一.在DOS界面下运行 pip3 install requests 二.切换至request目录下 cd E:\ python3 setup.py install ----- ...

  5. Kali Linux:使用nmap扫描主机

    nmap-Network Mapper,是著名的网络扫描和嗅探工具包.他同样支持Windows和OS X. 扫描开放端口和判断操作系统类型 先让我们ping一段地址范围,找到启动的主机: # nmap ...

  6. I.MX6 AR8031 寄存器操作

    /*************************************************************************** * I.MX6 AR8031 寄存器操作 * ...

  7. CentOS 6.5添加网易163源

    换国内的yum源. 准备工作,首先备份/etc/yum.repos.d/CentOS-Base.repo              cd /etc/yum.repos.d/ wget http://m ...

  8. 接口测试基础——第一篇smtplib发送文字邮件

    现在我们就开始进入接口测试框架的知识准备阶段,今天是第一篇,很简单的,就是发送纯文字的电子邮件,会的童鞋可以忽略,不会的就多敲几遍,直到自己能敲出来为止~~ # coding: utf-8 impor ...

  9. 剑指offer-第七章面试案例1(字符串转换为整型)

    //将字符串转换为整型 //思路:特殊的输入测试: //1,考虑字符串是否为空.2.字符串问空的时候的返回0,和真实的返回0直键的区别.3,字符串中出现0~9的字符处理 //4.字符串中出现*,¥等一 ...

  10. RESTful 服务示例

    WCF服务轻量级服务,可供JS调用 返回值格式:XML.Json 工程结构: 示例代码: using System; using System.Collections.Generic; using S ...