poj3666 线性dp
要把一个序列变成一个不严格的单调序列,求最小费用
/*
首先可以证明最优解序列中的所有值都能在原序列中找到
以不严格单增序列为例,
a序列为原序列,b序列为升序排序后的序列
dp[i][j]表示处理到a中第i个数,这些数中最大值为b[j]的费用,由单调性可知第i个数肯定变为b[j]
那么dp[i][j]等价于第i个数变成b[j]的费用
那么有 dp[i][j]=abs(b[j]-a[i])+min(dp[i-1][k]),k<=j
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 2005
#define ll long long
ll n,a[maxn],b[maxn],dp[maxn][maxn]; ll solveup(){
sort(b,b+n);
memset(dp,,sizeof dp);
for(int i=;i<n;i++)
dp[][i]=abs(a[]-b[i]);//初始条件 for(int i=;i<n;i++){
ll Min=dp[i-][];
for(int j=;j<n;j++){
Min=min(Min,dp[i-][j]);//单调增加的集合可以直接用Min来维护
dp[i][j]=abs(a[i]-b[j])+Min;
}
} ll ans=dp[n-][];//求结果
for(int i=;i<n;i++)
ans=min(ans,dp[n-][i]);
return ans;
} int main(){
while(scanf("%lld",&n)==){
for(int i=;i<n;i++)scanf("%lld",&a[i]),b[i]=a[i];
printf("%lld\n",solveup());
}
}
可以用滚动数组实现,空间省了许多
/*
滚动数组解法,第一维可以省去,dp[j]表示已经完成的序列用的最大值是b[j],状态i会覆盖状态i-1并且没有影响
dp[j]=abs(a[i]-b[j])+min(dp[k]),k<=j
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 2005
#define ll long long ll n,a[maxn],b[maxn],dp[maxn];
ll solve(){
sort(b,b+n);
for(int j=;j<n;j++)
dp[j]=abs(a[]-b[j]); for(int i=;i<n;i++){
ll Min=dp[];
for(int j=;j<n;j++){
Min=min(Min,dp[j]);
dp[j]=abs(a[i]-b[j])+Min;
}
} ll ans=dp[];
for(int j=;j<n;j++) ans=min(ans,dp[j]);
return ans;
} int main(){
while(scanf("%lld",&n)==){
for(int i=;i<n;i++)scanf("%lld",&a[i]),b[i]=a[i];
printf("%lld\n",solve());
}
}
poj3666 线性dp的更多相关文章
- POJ3666 线性dp_离散化_贪心
POJ3666 线性dp_离散化_贪心 就DP而言这个题不算难,但是难就难在贪心,还有离散化的思想上 题目大意:n个土堆,问你最少移动多少单位的图,可以使得这n个土堆变成单调的 dp[i][j]表示前 ...
- LightOJ1044 Palindrome Partitioning(区间DP+线性DP)
问题问的是最少可以把一个字符串分成几段,使每段都是回文串. 一开始想直接区间DP,dp[i][j]表示子串[i,j]的答案,不过字符串长度1000,100W个状态,一个状态从多个状态转移来的,转移的时 ...
- Codeforces 176B (线性DP+字符串)
题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成 ...
- hdu1712 线性dp
//Accepted 400 KB 109 ms //dp线性 //dp[i][j]=max(dp[i-1][k]+a[i][j-k]) //在前i门课上花j天得到的最大分数,等于max(在前i-1门 ...
- 动态规划——线性dp
我们在解决一些线性区间上的最优化问题的时候,往往也能够利用到动态规划的思想,这种问题可以叫做线性dp.在这篇文章中,我们将讨论有关线性dp的一些问题. 在有关线性dp问题中,有着几个比较经典而基础的模 ...
- POJ 2479-Maximum sum(线性dp)
Maximum sum Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33918 Accepted: 10504 Des ...
- poj 1050 To the Max(线性dp)
题目链接:http://poj.org/problem?id=1050 思路分析: 该题目为经典的最大子矩阵和问题,属于线性dp问题:最大子矩阵为最大连续子段和的推广情况,最大连续子段和为一维问题,而 ...
- nyoj44 子串和 线性DP
线性DP经典题. dp[i]表示以i为结尾最大连续和,状态转移方程dp[i] = max (a[i] , dp[i - 1] + a[i]) AC代码: #include<cstdio> ...
- 『最大M子段和 线性DP』
最大M子段和(51nod 1052) Description N个整数组成的序列a[1],a[2],a[3],-,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的.如果M &g ...
随机推荐
- java中BorderLayout的使用方法
相关设置: 使用BorderLayout布局上下左右中布局5个按键,单击中间的那个按键时就关闭窗口 代码: /**** *java中BorderLayout的使用方法 * 使用BorderLayout ...
- 在子类中调用父类的方法super
1.没有super之前,在子类里面需要父类里面的逻辑,但是我们是通过派生(自己定义了一个init,增加了一条line) class vehichle:#定义一个交通工具的类 Country=" ...
- python字典遍历的几种方法
(1)遍历key值 >>> a {'} >>> for key in a: print(key+':'+a[key]) a:1 b:2 c:3 >> ...
- Python基础【day03】:字典(一)
本节内容 简述 语法 字典的使用 字典内置方法 一.简述 字典是Python中的又一种数据结构,它是通过key-value的数据类型,跟我们小时候用的新华字典差不多,通过key去访问value 二.语 ...
- python---redis缓存页面前戏之剖析render源码
1.初始代码: def get(self, *args, **kwargs): import time tm = time.time() self.render('home/index.html', ...
- python---ORM之SQLAlchemy(4)relationship多对多练习
练习一:朋友 import sqlalchemy from sqlalchemy import create_engine from sqlalchemy import Column, String, ...
- cdqz2017-test10-rehearsal(CDQ分治&可持久化线段树&单调栈)
题意: 给出n个三元组 e[i]=(si,ti,wi) 第i个三元组的价值为 Σ w[j] ,j 满足以下4个条件: 1.j<i 2.tj<ti 3.sj<si 4.不存在j< ...
- JavaSE回顾及巩固的自学之路(四)——————方法和数组,面向对象
今天是2018.03.31,emmmmmm.好像距离上一次写Javase回顾总结已经好久好久过去,差一点就以为要停更了,哈哈哈. 其实呢,最近是真的好忙(额,这段时间觉得自己一直在学习) ...
- EntityFramework用法探索(八)事务处理
使用 前文中描述的Retail示例 ,在Customer对象的Mapping中设置Name属性:我们构造一个有效的Customer对象,再构造一个无效的Name属性为空的对象. DomainModel ...
- CF448C Painting Fence (贪心分治)
题面 \(solution:\) 一道蛮水的分治题,但思想很不错(虽然我还是非常天真的以为是积木大赛原题,并且居然还有30分) 看到这个题目,根据贪心的一贯风格,我们肯定能想到将整个栅栏的下面某部分直 ...