acm区间dp{离散化}

本周主要把时间放在复习类和学习运算符重载,想在回想一下这几周的动态规划感觉又忘了不少,一下是本周对几个我认为必要知识点的复习和学习。
1cin输入流的用时较长的问题
解决方案
使用cin.tie(0);ios::sync_with_stdio(0);进行解绑操作
2滚动数组是用时间换空间的一种优化思想。
简单的理解就是每次都使用固定的几个存储空间达到压缩节省存储空间的作用,主要应用在递推或动态规划中(背包问题,最大m字段和问题)。DP题目是一个自底向上的扩展过程,经常用到的是连续的解,前面的解经常可以舍去。所以可以用滚动数组。利用滚动数组在N很大的情况下可以实现压缩存储的作用.
3unique去重
不管是离散化还是普通规划,用unique去重是个极好的方法。
unique函数属于STL中比较常用函数,它的功能是元素去重。即”删除”序列中所有相邻的重复元素(只保留一个)。此处的删除,并不是真的删除,而是指重复元素的位置被不重复的元素给占领了(百度)
4基本实现代码
基础吗入下
memset(dp,0x3f,sixeof());
for(int i=1,i<=n;i++)
dp[i][i]=0;
for(int len=2;len<=n;len++)
{
for(int i=1,j=len;j<=n;j++,i++)
{
//dp实现方程
}
}
在这里插入代码片
给定-一个长度为n的序列A,构造一个长度为n的序列B ,满足b非严格单调,并且最小

化S=Zi=aN AiBil,求出这个最小值S1<=<=000.1<=Ai<=1e9.
即(【A[i]-B[i]的绝对值全部相加

定义:dp[i][j]:前i个数不下降,第i个数凑成v[j]时的最小花费dp[i][j]=min(dp[i- 1][k]+abs (a[i]-b[j]))(1<=i<=n, 0<=k<= j

用一个minn来记录1到当前j的dp[i-1][k]的最小值.我们就优化成:

dp[i][j]-minn+abs (a[i]-b[j])(1<=i<=n, 0<=j

j最大可达到1, 000, 000, 000, 枚举的话- -定会TLE, 而n的大小

最大只有2000,那么使用离散化的思想,先对序列a[i]进行处理.

在这里插入代码片

int main ()

#include 

#define inf 0x3f3f3f3f

using namespace std;

typedef long long int LL;

const double eps = 1e- -8;

const int maxn = 2005;

int n;

int a[maxn], dp[maxn] [maxn], num [maxn];

map<int, int> mp;

while (scanf("%d", &n) != E0F) {

int cnt.= 0;

for(inti=1;i<=n;i++)[

scanf("%d", &a[i]);

num[i] = a[i];

sort(num+1,num+1+n);

cnt=unique(num+1,num+1+n)-num-1;memset (dp, inf, sizeof (dp)) ;

dp[0][0] = 0;

]

memset (dp, inf, sizeof (dp));

dp[0][0] = 0;

for(inti=1;i<=n;i++)l

int val = dp[i - 1][0];

for(intj=1;j<=cnt;j++){

if(dp[i - 1][j] < val)[

val = dp[i - 1][j];

dp[i][j] =val + abs(a[i] - num[j]);

int ans = inf;

for(inti=1;i<=cnt;i++)l

ans = min(ans, dp[n][i]);
printf(" %d(n", ans) ;

return 0;
}


你可能感兴趣的:(acm区间dp{离散化})