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,只能求 ...
随机推荐
- Json转换为对象
JObject paramsList = JObject.Parse(OOOO); var obj = paramsList["AAAA"];
- ActiveRecord中andFilterWhere使用
查询数据库时 $model; if(!empty($name)) { $model->andWhere(['name'=>$name]); } 可以用andFilterWhere,自动的把 ...
- ubuntu14.10建立热点wifi分享给手机
http://jingyan.baidu.com/article/363872ecd8f35d6e4ba16f97.html ubuntu14.10建立热点wifi分享给手机
- Uva11134 Fabled Rooks
普通的贪心题. 虽然图是二维的,但可以把横向和纵向分开处理. 将区间按右端点排序,然后从区间左端点到右端点找第一个空位置放棋子即可. /*by SilverN*/ #include<algori ...
- JAVA输入一个整数,求出其所有质因数
首先得求出能整除A的数,再判断I是否是质数!!! import java.util.*; public class aa { public static void main(String[] args ...
- ZOJ 3430 Detect the Virus
传送门: Detect the Virus ...
- 微型 ORM-FluentData 温故知新系列
http://www.cnblogs.com/_popc/archive/2012/12/26/2834726.html 引言:FluentData 是微型 ORM(micro-ORM)家族的一名新成 ...
- IDE 集成开发环境
集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器.编译器.调试器和图形用户界面工具.集成了代码编写功能 ...
- html5+监听设备加速度变化信息
watchAcceleration 监听设备加速度变化信息 Number plus.accelerometer.watchAcceleration( successCB, errorCB, optio ...
- JSP 使用
JSP教程: http://www.w3cschool.cc/jsp/jsp-tutorial.html jsp语法: 任何语言都有自己的语法,JAVA中有,JSP虽然是在JAVA上的一种应用,但是依 ...