hdu 3666 Making the Grade

题目大意

给出了一列数,要求通过修改某些值,使得最终这列数变成有序的序列,非增或者非减的,求最小的修改量。

分析

首先我们会发现,最终修改后,或者和前一个数字一样,或者和后一个数字一样,这样才能修改量最小。

我们先根据原数列排序,确定元素的大小关系,对应编号为p[i]

dp[i][j] 表示考虑前i个元素,最后元素为序列中 第j小元素的最优解

dp[i][j] = MIN(dp[i-1][k]) + abs(a[i]-a[p[j]]), (0<k<=j)

刚开始以为是o(n^3)的复杂度,后来想想,k值在每次j循环的时候就能确定最小值

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define INF 100000000000000
 7 #define maxn 2005
 8 using namespace std;
 9 int n;
10 typedef long long LL;
11 LL a[maxn],b[maxn];
12 LL dp[maxn][maxn];
13 int main()
14 {
15     while(scanf("%d",&n)!=EOF)
16     {
17         for(int i=1; i<=n; i++)
18         {
19             scanf("%I64d",&a[i]);
20             b[i]=a[i];
21         }
22         sort(b+1,b+1+n);
23         for(int i=1; i<=n; i++)
24             for(int j=1; j<=n; j++)
25                 dp[i][j]=INF;
26         for(int j=1; j<=n; j++)
27         {
28             dp[1][j]=(a[1]-b[j]);
29             if(dp[1][j]<0)
30                 dp[1][j]=-dp[1][j];
31         }
32
33         for(int i=2; i<=n; i++)
34         {
35             LL k=dp[i-1][1];
36             for(int j=1; j<=n; j++)
37             {
38                 k=min(dp[i-1][j],k);
39                 LL tem=(a[i]-b[j]);
40                 if(tem<0)
41                     tem=-tem;
42                 dp[i][j]=min(dp[i][j],k+tem);
43                 // printf("==%I64d\n",dp[i][j]);
44             }
45         }
46         LL minn=INF;
47         for(int i=1; i<=n; i++)
48             minn=min(minn,dp[n][i]);
49         printf("%I64d\n",minn);
50     }
51     return 0;
52 }
时间: 2024-07-30 10:19:06

hdu 3666 Making the Grade的相关文章

POJ 3666 Making the Grade [DP]

题意: 给定一个序列,以最小代价将其变成单调不增或单调不减序列,这里的代价看题目公式. 思路: 很容易想到是DP. 1. 对前i个序列,构成的最优解其实就是与两个参数有关.一个是这个序列处理后的最大值mx,和这个序列处理的代价值cost. 显然最大值mx最小最好(这样第i+1个值可以不花代价直接接在其后面的可能性更大),cost最小也最好(题意要求),但是两者往往是鱼和熊掌. 用dp[i][j]表示:前i个数构成的序列,这个序列最大值为j,dp[i][j]的值代表相应的cost. 所以状态转移方

[2016-03-28][POJ][3666][]Making the Grade]

时间:2016-03-28 17:23:08 星期一 题目编号:[2016-03-28][POJ][3666][]Making the Grade] 分析:dp[i][j]表示把改到第i个数,且把a[i]改成b[i]需要的最少代价,已知b[j]递增,dp[i][j]由dp[i - 1][k]递推过来,如果改成非增,那么就要求 a[j] <= a[k],所以dp[i][j] = min(dp[i - 1][k] + d) k < j; #include <algorithm> #in

Poj 3666 Making the Grade (排序+dp)

题目链接: Poj 3666 Making the Grade 题目描述: 给出一组数,每个数代表当前位置的地面高度,问把路径修成非递增或者非递减,需要花费的最小代价? 解题思路: 对于修好的路径的每个位置的高度肯定都是以前存在的高度,修好路后不会出现以前没有出现过得高度 dp[i][j]代表位置i的地面高度为第j个高度,然后我们可以把以前的路修好后变成非递减路径,或者把以前的路径首尾颠倒,然后修成非递减路径.状态转移方程为:dp[i][j] = min(dp[i-1][k]) + a[i] -

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

传送门: http://poj.org/problem?id=3666 Making the Grade Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9468   Accepted: 4406 Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would lik

Hdu 3666 THE MATRIX PROBLEM(差分约束)

题目地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=3666 思路:差分约束. 取对数将乘除转化为加减. L<=m[i][j]*a[i]/b[j]<=U log(L/m[i][j])<=log(a[i])-log(b[j])<=log(U/m[i][j]) 则 : log(a[i])<=log(b[j])+log(U/m[i][j]) log(b[j])<=log(a[i])+log(m[i][j]/L) SPFA判

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

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

POJ 3666 Making the Grade

传送门:http://poj.org/problem?id=3666 解题思路: dp[i][j]:代表第i个数以j结尾所花的代价..那么dp[i][j]=fabs(a[i]-j)+min(dp[i-1][k])k<j; 实现代码: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cmath>

poj 3666 Making the Grade (动态规划)

Making the Grade Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4647   Accepted: 2202 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

poj 3666 Making the Grade &amp; zoj 3512 Financial Fraud 左偏树 or dp

//poj 3666 //分析:只是在2005年集训队论文黄源河提到的题目上略微有一点点变化 1 #include"iostream" 2 #include"cstdio" 3 using namespace std; 4 const int maxn = 2100; 5 int v[maxn],l[maxn],r[maxn],d[maxn]; //节点信息 6 int N; 7 int tot,root[maxn],num_now[maxn],num_del[ma