DP:Making the Grade(POJ 3666)

题目大意:就是农夫要修一条路,现在要求这条路要么就是上升的,要么就是下降的,总代价为∑|a[i]-b[i]|,求代价最低的修路方案, (0 ≤ β≤ 1,000,000,000) , (1 ≤ N ≤ 2,000)
这一题百分百就是DP了,为什么?我们现在就是要让cost最小,但是我们不知道cost应该怎么才能最小。
我们可以这么想,因为序列总是上升或者下降的,我们可以考虑上升的情况,假设前几个数组成的最大值为β,我们要考虑从0-β的改变值,然后不断推到第n个序列。
显然,这样的复杂度为0(Nβ^2),当然这样的复杂度显然是出事的。
现在我们想着优化这个东西,我们可以这么想,如果我们像之前那样扫描的话,那么其实我们忽略了一个很重要的事实,就是在变到α(α<β),其实对于α+1~β之内不会对α造成影响,于是我们可以用一个最小值的临时变量储存在α之前的最小值,用这个更新dp即可,那样就少了一次扫β的复杂度
复杂度变为O(Nβ);
但是如果仅仅是这样的话,绝对是TLE,因为β实在是太大了。
那么我们就要用到离散化的思想,把β投影到有限区域中,既然β是大小的函数,那么我们把可以这样对应:我们只用把新的序列按从小到大排列,然后只对下标进行查找就可以了,这样我们就把解的空间变到下标中了。
最后状态转移方程:dp[i-1][j]=ABS(a[i]-b[j])+min(dp[i-1][j]);(用滚动数组就可以了)
另外这一题还有一个更快的解法,那就是用左式堆去解,这个我晚一点开一个新的随笔写好了
#include <iostream>
#include <functional>
#include <algorithm>
#define ABS(a,b) (a-b) > 0 ? (a-b):(b-a) using namespace std; static int road[];
static int new_road[];
static long long dp1[];
static long long dp2[]; int fcmop1(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
int fcmop2(const void *a, const void *b)
{
return *(int *)b - *(int *)a;
} long long Search_Increase(const int);
long long Search_Decrease(const int); int main(void)
{
int n;
long long ans1, ans2;
while (~scanf("%d", &n))
{
for (int i = ; i < n; i++)
{
scanf("%d", &road[i]);
new_road[i] = road[i];
}
qsort(new_road, n, sizeof(int), fcmop1);
ans1 = Search_Increase(n);
printf("%lld", ans1);
/*
这题有问题,只用求不下降序列就可以了,如果求不上升序列会出错
qsort(new_road, n, sizeof(int), fcmop2);
ans2 = Search_Decrease(n);
printf("%lld\n", min(ans1, ans2));
*/
} return ;
} long long Search_Increase(const int n)
{
memset(dp1, , sizeof(dp1));
memset(dp2, , sizeof(dp2)); long long min_tmp, *dp_tmp = NULL, *p1 = dp1, *p2 = dp2, ans; for (int i = ; i < n; i++)
{
min_tmp = p1[];
for (int j = ; j < n; j++)
{
min_tmp = min(min_tmp, p1[j]);
p2[j] = (ABS(road[i], new_road[j])) + min_tmp;
}
dp_tmp = p1; p1 = p2; p2 = dp_tmp;
}
ans = p1[];
for (int i = ; i < n; i++)
ans = min(ans, p1[i]);
return ans;
} long long Search_Decrease(const int n)
{
memset(dp1, , sizeof(dp1));
memset(dp2, , sizeof(dp2)); long long min_tmp, *dp_tmp = NULL, *p1 = dp1, *p2 = dp2, ans; for (int i = ; i < n; i++)
{
min_tmp = p1[];
for (int j = ; j < n; j++)
{
min_tmp = min(min_tmp, p1[j]);
p2[j] = ABS(road[i], new_road[j]) + min_tmp;
}
dp_tmp = p1; p1 = p2; p2 = dp_tmp;
}
ans = p1[];
for (int i = ; i < n; i++)
ans = min(ans, p1[i]);
return ans;
}
另外这一题有BUG,那就是只用找不下降序列就可以了,两个都找会出错。。。。。

DP:Making the Grade(POJ 3666)的更多相关文章
- S - Making the Grade POJ - 3666 结论 将严格递减转化成非严格的
S - Making the Grade POJ - 3666 这个题目要求把一个给定的序列变成递增或者递减序列的最小代价. 这个是一个dp,对于这个dp的定义我觉得不是很好想,如果第一次碰到的话. ...
- A-Making the Grade(POJ 3666)
Making the Grade Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4656 Accepted: 2206 ...
- Making the Grade POJ - 3666
A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would l ...
- Poj 3666 Making the Grade (排序+dp)
题目链接: Poj 3666 Making the Grade 题目描述: 给出一组数,每个数代表当前位置的地面高度,问把路径修成非递增或者非递减,需要花费的最小代价? 解题思路: 对于修好的路径的每 ...
- 「POJ 3666」Making the Grade 题解(两种做法)
0前言 感谢yxy童鞋的dp及暴力做法! 1 算法标签 优先队列.dp动态规划+滚动数组优化 2 题目难度 提高/提高+ CF rating:2300 3 题面 「POJ 3666」Making th ...
- 把一个序列转换成非严格递增序列的最小花费 POJ 3666
//把一个序列转换成非严格递增序列的最小花费 POJ 3666 //dp[i][j]:把第i个数转成第j小的数,最小花费 #include <iostream> #include < ...
- POJ - 3666 Making the Grade(dp+离散化)
Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...
- POJ 3666 Making the Grade(数列变成非降序/非升序数组的最小代价,dp)
传送门: http://poj.org/problem?id=3666 Making the Grade Time Limit: 1000MS Memory Limit: 65536K Total ...
- POJ 3666 Making the Grade(二维DP)
题目链接:http://poj.org/problem?id=3666 题目大意:给出长度为n的整数数列,每次可以将一个数加1或者减1,最少要多少次可以将其变成单调不降或者单调不增(题目BUG,只能求 ...
随机推荐
- word中打出希腊字母
作为一个键盘党,不喜欢用鼠标去选择希腊字母,希望只用键盘就能在word中打出希腊字母. 方法是:按照下图所示对应表,先输入英文字母,然后选中它并按Ctrl+Shift+Q
- BZOJ3098 Hash Killer II
Description 这天天气不错,hzhwcmhf神犇给VFleaKing出了一道题: 给你一个长度为N的字符串S,求有多少个不同的长度为L的子串. 子串的定义是S[l].S[l + 1].... ...
- [NOIP2011] 普及组
数字反转 小模拟 #include<cstdio> #include<iostream> #include<cstring> using namespace std ...
- [IOS Block和delegate的对比]
原文:http://blog.sina.com.cn/s/blog_9e8867eb0102uykn.html 这篇文章建议和前一篇一起看, 另外先弄清楚IOS的block是神马东东. 委托和bloc ...
- Knockout Grid - Loading Remote Data
http://wijmo.com/grid-with-knockout-viewmodel-loading-remote-data/ We were hearing quite a few peopl ...
- CentOS 设置网络(修改IP&修改网关&修改DNS)--update.14.08.15
自己电脑上装的虚拟机用桥接方式连接物理机,虚拟机重启后ip会发生变化,非常阻碍Xshell的连接和hosts指定的dns. 通过修改IP为static模式,保持IP不变. ============== ...
- Windows下安装配置SubVersion的简明步骤
[使用的安装程序和文档说明] svn-1.4.0-setup.exe:Subversion服务端1.4.0安装程序: SubService.rar: SubServe服务Windows辅助工具; T ...
- hoj3152-Dice 等比数列求和取模
http://acm.hit.edu.cn/hoj/problem/view?id=3152 Dice My Tags (Edit) Source : Time limit : sec Memory ...
- C++编程思想重点笔记(下)
上篇请看:C++编程思想重点笔记(上) 宏的好处与坏处 宏的好处:#与##的使用 三个有用的特征:字符串定义.字符串串联和标志粘贴. 字符串定义的完成是用#指示,它容许设一个标识符并把它转化为字符串, ...
- MATLAB对话框设计[转]
Matlab之对话框 对话框设计:在图形用户界面程序设计中,对话框是重要的信息显示和获取输入数据的用户界面对象. 1.公共对话框: 公共对话框是利用windows资源的对话框,包括文件打开.文件保存. ...