[dp]HDOJ4960 Another OCD Patient
题意: 给一个n, 第二行给n堆的价值v[i], 第三行给a[i]. a[i]表示把i堆合在一起需要的花费.
求把n堆变成类似回文的 需要的最小花费.
思路:
①记忆化搜索 比较好理解...
dp[l][r] 记录l到r的最小花费
枚举对称轴 维护每次l到r之间对称
dp[l][r]=min(dp[l][r], a[cur-l]+a[r-i]+dfs(cur+1, i-1));
l左边和r右边的合并
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cctype>
#include <cmath>
#include <string>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <iomanip>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
typedef long long LL;
typedef long double LD;
#define pi acos(-1.0)
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
typedef pair<int, int> PI;
typedef pair<int, PI> PP;
#ifdef _WIN32
#define LLD "%I64d"
#else
#define LLD "%lld"
#endif
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//LL quick(LL a, LL b){LL ans=1;while(b){if(b & 1)ans*=a;a=a*a;b>>=1;}return ans;}
//inline int read(){char ch=' ';int ans=0;while(ch<'0' || ch>'9')ch=getchar();while(ch<='9' && ch>='0'){ans=ans*10+ch-'0';ch=getchar();}return ans;}
inline void print(LL x){printf(LLD, x);puts("");}
//inline void read(double &x){char c = getchar();while(c < '0') c = getchar();x = c - '0'; c = getchar();while(c >= '0'){x = x * 10 + (c - '0'); c = getchar();}} int a[];
LL num[];
int cost[];
int dp[][];
int dfs(int l, int r)
{
if(dp[l][r]!=-)
return dp[l][r];
if(l>=r)
return dp[l][r]=;
dp[l][r]=cost[r-l];
int cur=l;
for(int i=r;i>=l;i--)
{
for(;cur<i && (num[cur]-num[l-]<num[r]-num[i-]);cur++);
if(cur==i)
break;
if(num[cur]-num[l-]==num[r]-num[i-])
dp[l][r]=min(dp[l][r], cost[cur-l]+cost[r-i]+dfs(cur+, i-));
}
return dp[l][r];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int n;
while(~scanf("%d", &n) && n)
{
num[]=;
for(int i=;i<=n;i++)
{
scanf("%d", &a[i]);
num[i]=num[i-]+(LL)a[i];
}
for(int i=;i<n;i++)
scanf("%d", &cost[i]);
for(int i=;i<=n;i++)
fill(dp[i]+i+, dp[i]+n+, -);
//memset(dp, -1, sizeof(dp));
printf("%d\n", dfs(, n));
}
return ;
}
HDOJ 4960 记忆化搜索
② 区间dp
结构体里有 SUM和NUM记录 左或右 NUM堆合起来 合成总值为SUM的
左边从1开始往右 右边从n开始往左
Lsum==Rsum了就分别把Lsum合起来 Rsum合起来 分别存进L和R 然后继续往中间
Ltmp和Rtmp分别记录左边和右边分别合到哪里了
L R 搞完以后 按顺序把 L 中间 R 放进final (注意中间)
因为对称 所以只要 dp final 的一半就够了
dp[i]=min(dp[i], dp[j]+cost[左个数]+cost[右个数]);
最后要注意合了 i堆之后 把剩下的全合起来的情况
ans=min(ans, dp[i]+cost[剩下堆数]);
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cctype>
#include <cmath>
#include <string>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <iomanip>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
typedef long long LL;
typedef long double LD;
#define pi acos(-1.0)
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
typedef pair<int, int> PI;
typedef pair<int, PI> PP;
#ifdef _WIN32
#define LLD "%I64d"
#else
#define LLD "%lld"
#endif
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//LL quick(LL a, LL b){LL ans=1;while(b){if(b & 1)ans*=a;a=a*a;b>>=1;}return ans;}
//inline int read(){char ch=' ';int ans=0;while(ch<'0' || ch>'9')ch=getchar();while(ch<='9' && ch>='0'){ans=ans*10+ch-'0';ch=getchar();}return ans;}
inline void print(LL x){printf(LLD, x);puts("");}
//inline void read(double &x){char c = getchar();while(c < '0') c = getchar();x = c - '0'; c = getchar();while(c >= '0'){x = x * 10 + (c - '0'); c = getchar();}} struct node
{
LL SUM;
int NUM;
}L[], R[], final[];
LL dp[];
int a[];
int cost[];
int Ltop, Rtop, top;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int n;
while(~scanf("%d", &n) && n)
{
memset(L, , sizeof(L));
memset(R, , sizeof(R));
memset(final, , sizeof(final));
memset(a, , sizeof(a));
memset(cost, , sizeof(cost));
for(int i=;i<=n;i++)
scanf("%d", &a[i]);
for(int i=;i<=n;i++)
scanf("%d", &cost[i]); LL Lsum=a[], Rsum=a[n];
int Lnum=, Rnum=;
Ltop=Rtop=;
int Ltmp=, Rtmp=n;
for(int i=, j=n; i<j;)
{
while(Lsum!=Rsum)
{
if(i==j)
break;
if(Lsum<Rsum)
{
Lnum++;
Lsum+=a[++i];
}
else if(Rsum<Lsum)
{
Rnum++;
Rsum+=a[--j];
}
}
if(Lsum==Rsum)
{
L[Ltop].SUM=Lsum, L[Ltop++].NUM=Lnum;
R[Rtop].SUM=Rsum, R[Rtop++].NUM=Rnum;
Lsum=a[++i];
Rsum=a[--j];
Lnum=Rnum=;
Ltmp=i;
Rtmp=j;
}
}
top=;
for(int i=;i<Ltop;i++)
final[++top]=L[i];
if(Ltmp<=Rtmp)
{
int sum=;
for(int i=Ltmp;i<=Rtmp;i++)
sum+=a[i];
final[++top].SUM=sum, final[top].NUM=Rtmp-Ltmp+;
}
for(int i=Rtop-;i>=;i--)
final[++top]=R[i];
for(int i=;i<=top/;i++)
{
int tmp1=final[i].NUM, tmp2=final[top-i+].NUM;
dp[i]=LLONG_MAX;
for(int j=i-;j>=;j--)
{
dp[i]=min(dp[i], dp[j]+cost[tmp1]+cost[tmp2]);
tmp1+=final[j].NUM;
tmp2+=final[top-j+].NUM;
}
}
LL minn=LLONG_MAX;
LL ans=n;
for(int i=;i<=top/;i++)
{
minn=min(minn, dp[i]+cost[ans]);
ans-=final[i+].NUM+final[top-i].NUM;
}
print(minn);
}
return ;
}
HDOJ 4960 区间dp
[dp]HDOJ4960 Another OCD Patient的更多相关文章
- hdu 4960 Another OCD Patient(dp)
Another OCD Patient Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Ot ...
- HDU4960Another OCD Patient(间隙dp,后座DP)
Another OCD Patient Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Ot ...
- HDU 4960 Another OCD Patient(记忆化搜索)
HDU 4960 Another OCD Patient pid=4960" target="_blank" style="">题目链接 记忆化 ...
- hdu 4960 Another OCD Patient (最短路 解法
http://acm.hdu.edu.cn/showproblem.php?pid=4960 2014 Multi-University Training Contest 9 Another OCD ...
- [hdu4960]Another OCD Patient(区间dp)
题意:给出n个数,把这n个数合成一个对称的集合.每个数只能合并一次. 解题关键:区间dp,dp[l][r]表示l-r区间内满足条件的最大值.vi是大于0的,所以可以直接双指针确定. 转移方程:$dp[ ...
- HDU 4960 Another OCD Patient 简单DP
思路: 因为是对称的,所以如果两段是对称的,那么一段的前缀和一定等于另一段的后缀和.根据这个性质,我们可以预处理出这个数列的对称点对.然后最后一个对称段是从哪里开始的,做n^2的DP就可以了. 代码: ...
- HDU_4960 2014多校9 Another OCD Patient DP
其实现在想起来是个巨简单的DP,模型就跟LCS很像,比赛的时候居然没想出来,在聪哥提醒下还卡了个地方 就是说给定一串n个数字的序列,可以连续合并,最终使得序列是回文的,题目也给定了合并数字所需的代价, ...
- 【HDU4960】Another OCD Patient
题意 给出一个长度为n的整数序列.可以将一段连续的序列进行合并.合并的长度不同代价不同.问付出最少多少代价可以将这个序列变成一个对称的序列.n<=5000 分析 一看题感觉是个dp很好写啊.f[ ...
- HDU4960(SummerTrainingDay03-F dp)
Another OCD Patient Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Ot ...
随机推荐
- Sqlserver基于流程控制
流程控制语句只能在单个批处理段,用户自定义函数和存储过程中使用不能夸多个批处理或者用户自定义函数或者存储过程 批处理:一个或者多个语句组成的一个批处理,是因为所有语句一次性地被提交到一个sql实例,如 ...
- 通过自关联替代开窗函数实现SQL优化
数据库环境:SQL SERVER 2005 我们平时都是通过开窗析函数来取代自关联,减少表扫描,从而优化SQL.今天,反其道而行, 用自关联改写开窗函数.我们先来看一下SQL. 原SQL语句 SELE ...
- ###C中的extern-static-const关键词
#@date: 2014-06-14 #@author: gerui #@email: forgerui@gmail.com Contents extern的作用一般是用来声音一个外部变量和函数.一般 ...
- S.O.L.I.D
S.O.L.I.D.是一组面对面向对象设计的最佳实践的设计原则.术语来自Robert C.Martin的著作Agile Principles, Patterns, and Practices in C ...
- Entity Framework多对多关联映射的实现
Entity Framework是微软官方提供的一个ORM解决方案,它有纯正的血统,比NHibernate更容易使用并且与现有其它官方框架配合更加密切. 时代不断的在发展变化,记得10年前还是ADO( ...
- javascipt学习笔记1
一.javascript 部分 1.整理 <<javascript>> 要学习哪些章节 及核心内容? ①javascript简介 核心技术点:javascript定义 作用特点 ...
- CSS实现文字上标、下标
.sup{vertical-align:super; color:red; font-size:9px; font-family:Arial, Helvetica, sans-serif; margi ...
- nginx禁止目录php执行权限
nginx禁止目录php执行权限,找到配置fastcgi.conf文件,一般在/usr/local/nginx/conf/下面,修改如下 location ~* ^/(data|uploads|tem ...
- 《C和指针》读书笔记——第二章 基本概念
1.编译过程: source code→Compiler→Object code→Linker←Lib ↓ Exe 2.经过初始化的静态变量(static)在程序执行前能获得他们的值. 3.绝大多数环 ...
- iOS 浅复制、深复制、完全复制的知识点梳理验证(附加归档解档)
在之前转载的一片文章中,文中对浅复制和深复制进行了详细的解读,同时还提到了深复制(one-level-deep copy).完全复制(true copy)的概念,并指出iOS开发中的深复制是单层深赋值 ...