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,只能求 ...
随机推荐
- BZOJ-2190 仪仗队 数论+欧拉函数(线性筛)
今天zky学长讲数论,上午水,舒爽的不行..后来下午直接while(true){懵逼:}死循全程懵逼....(可怕)Thinking Bear. 2190: [SDOI2008]仪仗队 Time Li ...
- 【poj1182】 食物链
http://poj.org/problem?id=1182 (题目链接) 题意 中文题 Solution 带权并查集. 神犇博客,秒懂 fa记录父亲,r记录与父亲的关系.%3运用的很巧妙. 代码 / ...
- codeforces 288A:Polo the Penguin and Strings
Description Little penguin Polo adores strings. But most of all he adores strings of length n. One d ...
- 洛谷P1121 环状最大两段子段和
题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的第一行是一个正整数N,表示了序列 ...
- Linux File、File Directory IO Operation Summary(undone)
目录 . 引言 . Linux下文件操作API . Linux下文件目录操作API . Linux下的其他设备操作API 1. 引言 Linux支持多种文件系统,如ext.ext2.minix.iso ...
- adb devices找不着设备
第1步,查找设备VID VID是04E8,那么打开C:\Users\liujuan\Documents\.android\adb_usb.ini 在里面添加上设备即是 0x04E8,保存并关闭 然后c ...
- Mysql数据库的工作原理
- Java,PostgreSQL时间范围查询
遇到一坑:对于如下代码 select * from order_mileagefuel where date > '2015-11-1' and date< '2015-11-5' 在Po ...
- 神经网络训练中的Tricks之高效BP(反向传播算法)
神经网络训练中的Tricks之高效BP(反向传播算法) 神经网络训练中的Tricks之高效BP(反向传播算法) zouxy09@qq.com http://blog.csdn.net/zouxy09 ...
- day4作业之信息表
实在是太low了,终究是自己写的,记录下 #!/usr/bin/env python # coding=utf8 import os, re #这里我把查询这块分为3个函数了,纠结了很久是放一起还是分 ...