题意: 给一个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的更多相关文章

  1. hdu 4960 Another OCD Patient(dp)

    Another OCD Patient Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Ot ...

  2. HDU4960Another OCD Patient(间隙dp,后座DP)

    Another OCD Patient Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Ot ...

  3. HDU 4960 Another OCD Patient(记忆化搜索)

    HDU 4960 Another OCD Patient pid=4960" target="_blank" style="">题目链接 记忆化 ...

  4. hdu 4960 Another OCD Patient (最短路 解法

    http://acm.hdu.edu.cn/showproblem.php?pid=4960 2014 Multi-University Training Contest 9 Another OCD ...

  5. [hdu4960]Another OCD Patient(区间dp)

    题意:给出n个数,把这n个数合成一个对称的集合.每个数只能合并一次. 解题关键:区间dp,dp[l][r]表示l-r区间内满足条件的最大值.vi是大于0的,所以可以直接双指针确定. 转移方程:$dp[ ...

  6. HDU 4960 Another OCD Patient 简单DP

    思路: 因为是对称的,所以如果两段是对称的,那么一段的前缀和一定等于另一段的后缀和.根据这个性质,我们可以预处理出这个数列的对称点对.然后最后一个对称段是从哪里开始的,做n^2的DP就可以了. 代码: ...

  7. HDU_4960 2014多校9 Another OCD Patient DP

    其实现在想起来是个巨简单的DP,模型就跟LCS很像,比赛的时候居然没想出来,在聪哥提醒下还卡了个地方 就是说给定一串n个数字的序列,可以连续合并,最终使得序列是回文的,题目也给定了合并数字所需的代价, ...

  8. 【HDU4960】Another OCD Patient

    题意 给出一个长度为n的整数序列.可以将一段连续的序列进行合并.合并的长度不同代价不同.问付出最少多少代价可以将这个序列变成一个对称的序列.n<=5000 分析 一看题感觉是个dp很好写啊.f[ ...

  9. HDU4960(SummerTrainingDay03-F dp)

    Another OCD Patient Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Ot ...

随机推荐

  1. 读jQuery官方文档:数据方法与辅助方法

    数据方法 有时候你可能想要在元素上面储存数据.由于浏览器兼容性问题,用原生JavaScript处理元素上的数据可能会造成内存溢出,jQuery可以帮你自动处理这些问题: //储存和取出元素数据 $(' ...

  2. spark处理jsonFile

    按照spark的说法,这里的jsonFile是特殊的文件: Note that the file that is offered as jsonFile is not a typical JSON f ...

  3. 比较Activiti中三种不同的表单及其应用

    http://www.kafeitu.me/activiti/2012/08/05/diff-activiti-workflow-forms.html 开篇语 这个恐怕是初次接触工作流最多的话题之一了 ...

  4. 20个linux命令行工具监视性能(下)

    昨天晚上第一次翻译了<20 Command Line Tools to Monitor Linux Performance>中的前十个命令,翻译得不是很好,今天晚上继续把后面的十个也翻译给 ...

  5. Centos搭建PHP5.3.8+Nginx1.0.9+Mysql5.5.17

    操作环境 操作系统:Mac Os Lion 虚拟主机:VMware Fusion 虚拟系统:Centos 5.5+ 操作用户:Root 实现目的:搭建LNMP环境. 安装依赖库和开发环境 #依赖库和开 ...

  6. ios 兼容IPV4和IPV6网络通信

    前言: 苹果官方出了新的规定,要求新上架的app都必须单独支持ipv6-only的网络. 准备工作: 搭建IPV6测试环境:http://blog.csdn.net/potato512/article ...

  7. 01_SpringMVC流程架构图

    [组件说明] 以下组件通常使用框架提供实现: 1.DisPatcherServlet:前端控制器(不需要程序员开发) 用户请求到达前端控制器,它相当于MVC模式中的C(Controller),Disp ...

  8. Poj/OpenJudge 1042 Gone Fishing

    1.链接地址: http://bailian.openjudge.cn/practice/1042/ http://poj.org/problem?id=1042 2.题目: Gone Fishing ...

  9. 一个css3流程导图

    这也是公司用到的,写个demo出来分享 <!DOCTYPE html> <html> <head> <meta http-equiv="Conten ...

  10. html分页

    <div class="fy"> <a href="" title="上一页">上一页</a> < ...