Making the Grade
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 7068   Accepted: 3265

Description

A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would like. His cows do not mind climbing up or down a single slope, but they are not fond of an alternating succession of hills and valleys. FJ would like to add and remove dirt from the road so that it becomes one monotonic slope (either sloping up or down).

You are given N integers A1, ... , AN (1 ≤ N ≤ 2,000) describing the elevation (0 ≤ Ai ≤ 1,000,000,000) at each of N equally-spaced positions along the road, starting at the first field and ending at the other. FJ would like to adjust these elevations to a new sequence B1, . ... , BN that is either nonincreasing or nondecreasing. Since it costs the same amount of money to add or remove dirt at any position along the road, the total cost of modifying the road is

|AB1| + |AB2| + ... + |AN - BN |

Please compute the minimum cost of grading his road so it becomes a continuous slope. FJ happily informs you that signed 32-bit integers can certainly be used to compute the answer.

Input

* Line 1: A single integer: N
* Lines 2..N+1: Line i+1 contains a single integer elevation: Ai

Output

* Line 1: A single integer that is the minimum cost for FJ to grade his dirt road so it becomes nonincreasing or nondecreasing in elevation.

Sample Input

7
1
3
2
4
5
3
9

Sample Output

3

给定一个序列,以最小代价将其变成单调不增或单调不减序列,这里的代价看题目公式。

思路:

很容易想到是DP。

1.

对前i个序列,构成的最优解其实就是与两个参数有关。一个是这个序列处理后的最大值mx,和这个序列处理的代价值cost。

显然最大值mx最小最好(这样第i+1个值可以不花代价直接接在其后面的可能性更大),cost最小也最好(题意要求),但是两者往往是鱼和熊掌。

用dp[i][j]表示:前i个数构成的序列,这个序列最大值为j,dp[i][j]的值代表相应的cost。

所以状态转移方程如下:

dp[i][j]=abs(j-w[i])+min(dp[i-1][k]);(k<=j)

这个表格是根据转移方程写出来的dp数组。

再仔细看一下转移方程:dp[i][j]=abs(j-w[i])+min(dp[i-1][k]);(k<=j)

右边没填充的是因为填充的数字肯定比前面的数字大,无用,因为在求min( dp[i-1][k] )时,是求最小值,既然更大,则最小值时无需考虑。

又从表格中可以看出:

dp[i][j]=abs(j-w[i])+min(dp[i-1][k]);(k<=j)这里的k无需从1遍历到j。

只要在对j进行for循环的时候不断更新一个dp[i-1][j]的最小值mn=min(mn,dp[i-1][j]),

然后对dp[i][j]=abs(j-w[i])+mn即可;

这样改进之后即可从本来的时候时间复杂度O(NMM)改进为O(NM);

但是,这里的m是A[i]的最大值,显然TLE。

所以必须用离散化思想改进,因为N=2000。远小于A[i]的最大值。

离散化:将序列排序一下,然后用位置的前后关系来制定其值,这样时间复杂度变成O(N^2).

最后是这题数据有bug,只需要求不减序列即可。

?:谁能给我讲讲为什么这样离散化?为什么最后的结果中的每一个的数字都在原来的串中出现过?为什么这样得到的就是一个最优解?

附个解题报告,没太看懂他的证明

http://www.cnblogs.com/vb4896/p/5877962.html

 #include<iostream>
#include <cstdio>
#include<vector>
#include<algorithm>
#define Abs(a) ((a)>0?(a):-(a))
#define Mod(a,b) (((a)-1+(b))%(b)+1)
using namespace std;
const int N=;
const long long inf=(<<);
int n;
int a[N],b[N];
long long int dp[N][N];
void solve()
{
for(int i=;i<=n;i++)
{
long long mn=dp[i-][];
for(int j=;j<=n;j++)
{
mn=min(mn,dp[i-][j]);
dp[i][j]=Abs(a[i]-b[j])+mn;
}
}
long long ans=dp[n][];
for(int i=;i<=n;i++)
ans=min(ans,dp[n][i]);
printf("%lld\n",ans);
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",a+i);
b[i]=a[i];
}
sort(b+,b+n+);
solve(); return ;
}
题目给出了一列数,要求通过修改某些值,使得最终这列数变成有序的序列,非增或者非减的(数据很弱,只用求非严格递增即可),求最小的修改量。
首先我们会发现,最终修改后,或者和前一个数字一样,或者和后一个数字一样,这样才能修改量最小。
我们先根据原数列排序,确定元素的大小关系,对应编号为p[i]
dp[i][j] 表示考虑前i个元素,最后元素为序列中 第j小元素的最优解
dp[i][j] = MIN(dp[i-1][k]) + abs(a[i]-a[p[j]]), (0<k<=j)    // 非严格递增
 //二维解法
#include<iostream>
#include <cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=; int n;
__int64 a[N];
__int64 b[N]; bool cmp(__int64 a,__int64 b)
{
return a<b;
} __int64 dp[N][N];
__int64 min(__int64 x,__int64 y)
{
return x<y?x:y;
}
int main()
{
//freopen("in.txt","r",stdin);
__int64 i,j,k,ans;
cin>>n;
for(i=; i<=n; i++) {
scanf("%I64d",&a[i]);
}
for(i=; i<=n; i++) {
b[i]=a[i];
}
sort(b+,b++n,cmp);
for(j=; j<=n; j++) {
dp[][j]=a[]-b[j];
if(dp[][j]<) {
dp[][j]=-dp[][j];
}
}
__int64 t;
for(i=; i<=n; i++) { // 非严格递增
k=dp[i-][];
for(j=; j<=n; j++) {
k=min(dp[i-][j],k);
t=a[i]-b[j];
if(t<) {
t=-t;
}
dp[i][j]=k+t; //dp[i][j] = min{dp[i - 1][0...j] + ?abs(a[i] - b[j])}
}
}
ans=dp[n][n];
for(i=n; i>=; i--) {
ans=min(ans,dp[n][i]);
}
printf("%I64d\n",ans);
return ;
}
 //一维 (滚动数组)
#include<iostream>
#include <cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=;
__int64 a[N],b[N],dp[][N];
__int64 min(__int64 x,__int64 y)
{
return x<y?x:y;
}
int main()
{
int n,i,j;
__int64 k,t;
scanf("%d",&n);
for(i=; i<=n; i++) {
scanf("%I64d",&a[i]);
}
for(i=; i<=n; i++) {
b[i]=a[i];
}
sort(b+,b++n);
for(i=; i<=n; i++) {
dp[][i]=a[]-b[i];
if(dp[][i]<) {
dp[][i]=-dp[][i];
}
}
for(i=; i<=n; i++) {
k=dp[i%][];
for(j=; j<=n; j++) {
k=min(k,dp[i%][j]);
t=a[i]-b[j];
if(t<) {
t=-t;
}
dp[(i+)%][j]=k+t;
}
}
j=(n+)%;
k=dp[j][];
for(i=; i<=n; i++) {
k=min(k,dp[j][i]);
}
printf("%I64d\n",k);
return ;
}

poj 3666 Making the Grade(dp离散化)的更多相关文章

  1. [poj 3666] Making the Grade (离散化 线性dp)

    今天的第一题(/ω\)! Description A straight dirt road connects two fields on FJ's farm, but it changes eleva ...

  2. poj 3666 Making the Grade(dp)

    Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...

  3. Poj 3666 Making the Grade (排序+dp)

    题目链接: Poj 3666 Making the Grade 题目描述: 给出一组数,每个数代表当前位置的地面高度,问把路径修成非递增或者非递减,需要花费的最小代价? 解题思路: 对于修好的路径的每 ...

  4. POJ - 3666 Making the Grade(dp+离散化)

    Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...

  5. POJ 3666 Making the Grade(数列变成非降序/非升序数组的最小代价,dp)

    传送门: http://poj.org/problem?id=3666 Making the Grade Time Limit: 1000MS   Memory Limit: 65536K Total ...

  6. poj 3666 Making the Grade(离散化+dp)

    Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...

  7. POJ 3666 Making the Grade (线性dp,离散化)

    Making the Grade Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) T ...

  8. POJ 3666 Making the Grade(二维DP)

    题目链接:http://poj.org/problem?id=3666 题目大意:给出长度为n的整数数列,每次可以将一个数加1或者减1,最少要多少次可以将其变成单调不降或者单调不增(题目BUG,只能求 ...

  9. POJ 3666 Making the Grade (DP)

    题意:输入N, 然后输入N个数,求最小的改动这些数使之成非严格递增即可,要是非严格递减,反过来再求一下就可以了. 析:并不会做,知道是DP,但就是不会,菜....d[i][j]表示前 i 个数中,最大 ...

随机推荐

  1. Google Code Jam 2014 资格赛:Problem C. Minesweeper Master

    Problem Minesweeper is a computer game that became popular in the 1980s, and is still included in so ...

  2. MIC中示例程序计算π

    mic中编程十分简单,只需在普通程序中简单加几句就可以,使用 lspci|grep -i -co-processor 命令可以查看机器中是否插入MIC卡以及MIC卡的数目,MIC编程环境的配置这里就不 ...

  3. 算不算类似微信小程序

    这几天微信发布的微信里生成小程序,刷爆了朋友圈. 微信生成的小程序不用下载安装就能在手机里出现,即用即删. 想到这里,我想到苹果手机本身再带类似于微信的小程序的呈现方式,也可以即用即删,那是我在去年久 ...

  4. CentOS Linux解决网卡报错Bringing up interface eth0.....

    问题描述:在VMware里克隆出来的CentOS Linux,开机执行命令:ifconfig...没有看到eth0网卡.然后重启网卡又报以下错误:Bringing up interface eth0: ...

  5. hdu 5285 wyh2000 and pupil(二染色)

    第一次用vector解得题.值得纪念,这道题是二染色问题,我用bfs解得.就是染色,推断,计数问题,其 实挺简单的,就是得判一下特殊情况,当n<2的时候就不能有解,由于题目要求每一个组至少有一个 ...

  6. 【python】-- web开发之JavaScript

    JavaScript JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. ...

  7. 我的Android进阶之旅------>Android实现用Android手机控制PC端的关机和重启的功能(三)Android客户端功能实现

    我的Android进阶之旅------>Android实现用Android手机控制PC端的关机和重启的功能(一)PC服务器端(地址:http://blog.csdn.net/ouyang_pen ...

  8. did not find a matching property (tomcat+Eclipse 报错)

    警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclips ...

  9. Javaweb--- EL表达式 JSTL标准标签库

    一.EL表达式(expression language): 语法  ${...} jsp中page指令有一个属性叫isELIgnored, 用来标记此页面是否忽略EL表达式, 默认为false 举个例 ...

  10. mysql练习(待补充)

    2.查询‘生物’课程比‘物理’课程成绩高的所有学生的学号 思路: 获取所有生物课程的人(学号,成绩)-临时表 获取所有物理课程的人(学号,成绩)-临时表 根据学号连接两个临时表: 学号 生物成绩 物理 ...