Making the Grade(POJ3666)
题目大意:
给出长度为n的整数数列,每次可以将一个数加1或者减1,最少要多少次可以将其变成单调增或者单调减(不严格).
题解:
1.一开始我有一个猜想,就是不管怎么改变,最终的所有数都是原来的某个数。然而我并不会证明,然而我属于那种不彻底弄清楚就不会去写的那种顽固分子,于是就拖了好几天。网络上有很多关于此题的题解,确实用了这个猜想来离散化,但是都是讲怎么dp,然后最后扯一句“由于数据比较大,可以离散化”之类的话,要么就是相当粗略的证明(也许已经说的够清楚了只不过我没理解...)。
2.今天早上起来洗漱的时候,感觉头脑比较清醒,再次想了一下这个问题,想到一个自认为正确的证明:
记原来的数从小到大排序后分别是$a_1\ a_2\ a_3\cdots a_n$ 修改后从左到右分别是$b_1\ b_2\ b_3\cdots b_n$. 为了方便描述,在数轴上标出这些点,称为关键点。
假设存在$a_s<b_i<=b_{i+1}<=\cdots <=b_j<a_{s+1}$
情况一:如果这些b都相等,那么把这些b都改成$a_s$或者$a_{s+1}$ 肯定会有一种更优。
情况二:如果不全相等,那么肯定存在 $b_p\ b_{p+1}\ b_{p+2}\cdots b_q$,他们的值相等,那么把他们移到左边的关键点或者右边的关键点,肯定有一种会更加优. 不断这样移动,最后就变成情况一了。
综上至少存在一种最优方案,最终的所有数都是原来的某个数。
因此可以离散化之后做dp,dp[i][j]表示把前i个数变成单调增(不严格)且第i个数变成原来第j大的数的最小代价。
dp[i][j]=min{dp[i-1][1...j]}+abs(a[i]-b[j]).
单调减(不严格)的情况也一样,更加方便的是可以把原数组倒转后做单调增的dp。
另外这题和CF Codeforces Round #371 (Div. 1)的C题类似,有个超简单的nlogn做法。可以看这篇:http://www.cnblogs.com/vb4896/p/5894578.html
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cstdlib>
#include <set>
using namespace std; #define X first
#define Y second
#define Mod 1000000007
#define N 3010
typedef long long ll;
typedef pair<int,int> pii; inline int Mul(int x,int y){return 1ll*x*y%Mod;}
inline int Add(int x,int y){return ((x+y)%Mod+Mod)%Mod;} int n,m;
int a[N],b[N];
ll dp[N][N],Ans=1ll<<; void Solve()
{
for (int j=;j<=m;j++) dp[][j]=abs(b[j]-a[]);
for (int i=;i<=n;i++)
{
ll tmp=1ll<<;
for (int j=;j<=m;j++)
{
tmp=min(tmp,dp[i-][j]);
dp[i][j]=abs(b[j]-a[i]);
dp[i][j]+=tmp; }
}
for (int j=;j<=m;j++) Ans=min(Ans,dp[n][j]);
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout); scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i]=a[i]-i;
sort(b+,b+n+);
for (int i=;i<=n;i++) if (i== || b[i]!=b[i-]) b[++m]=b[i]; Solve();
printf("%I64d\n",Ans); return ;
}
Making the Grade(POJ3666)的更多相关文章
- Making the Grade [POJ3666] [DP]
题意: 给定一个序列,以最小代价将其变成单调不增或单调不减序列,代价为Σabs(i变化后-i变化前),序列长度<=2000,单个数字<=1e9 输入:(第一行表示序列长度,之后一行一个表示 ...
- POJ3666 Making the Grade
POJ3666 Making the Grade 题意: 给定一个长度为n的序列A,构造一个长度为n的序列B,满足b非严格单调,并且最小化S=∑i=1N |Ai-Bi|,求出这个最小值S,1<= ...
- BZOJ1592 POJ3666 [Usaco2008 Feb]Making the Grade 路面修整 左偏树 可并堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3666 题目传送门 - BZOJ1592 题意概括 整条路被分成了N段,N个整数A_1, ... , ...
- poj3666 Making the grade【线性dp】
Making the Grade Time Limit: 1000MS Memory Limit: 65536K Total Submissions:10187 Accepted: 4724 ...
- POJ3666 Making the Grade [DP,离散化]
题目传送门 Making the Grade Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9090 Accepted: ...
- poj3666 Making the Grade(基础dp + 离散化)
Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...
- LG2893/POJ3666 「USACO2008FEB」Making the Grade 线性DP+决策集优化
问题描述 LG2893 POJ3666 题解 对于\(A\)中的每一个元素,都将存在于\(B\)中. 对\(A\)离散化. 设\(opt_{i,j}\)代表\([1,i]\),结尾为\(j\)的最小代 ...
- [poj3666]Making the Grade(DP/左偏树)
题目大意:给你一个序列a[1....n],让你求一个序列b[1....n],满足 bi =a && bc,则最小的调整可以是把b变成c. 所以归纳可知上面结论成立. dp[i][j] ...
- 【POJ3666】Making the Grade 离散化+DP
学到了一个引理:在满足S最小化的条件下,一定存在一种构造序列B的方案,使得序列B中的数值都来自于A中.(数学归纳法+中位数定理得证) 对于状态的表示来说,首先肯定有一个 i ,表示选到了第 i 个数时 ...
随机推荐
- office2003?2007共存?版本各自打开的解决方案
在现在的办公软件中, Microsoft出品的 Office集成办公软件占据了绝大多数的市场份额,从最初的 Office 2000,到后面的 Office 2003以至近两年刚发行的 Office 2 ...
- dubbo(转载)
1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...
- jqury 右击事件插件
在有些时候,网页中需要给一些标签对象加入右击的事件,在网上看了一些小的插件,但是不能根据this获取到当前的标签.所以相对他们进行改进一下.自己写了一个小的js右击事件.废话不多说了,看代码. $(f ...
- Webpack参考资料
学习是一种进步,只有不断的向别人学习,才能提升自己.三人行必有我师焉 1. http://www.cnblogs.com/zhengjialux/p/5861845.html
- 【BZOJ】3436: 小K的农场
3436: 小K的农场 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 938 Solved: 417[Submit][Status][Discuss ...
- JavaScript中的方法重载
对js有些了解的人都知道,在js中根本就不存在像C#中的那种方法重载,而有的只是方法的覆盖,当你在js中敲入两个或多个同名的方法的时候,不管方法(函数)的参数个数怎么个不同,这个方法名只能属于最后定义 ...
- mysql order by in 的字符顺序
//MySQL 语句SELECT * FROM `MyTable`WHERE `id` IN (11,1,111) ORDER BY FIELD(`id`, 11,1,111); laravel 框架 ...
- AOP 面向切面编程
AOP http://blog.csdn.net/xiang_j2ee/article/details/6851963 Android 支持 AspectJ 这个库来实现面向切面编程. 使用 Apac ...
- Eenterprise linux服务器分区
分区说明: (在MBR格式的硬盘下我会分/ /boot swap /data 四个分区,不建议在服务器上面使用LVM,中大型企业的IDC都是有存储区域的,专门管理硬盘容量的.)(分区的时候,请注意顺序 ...
- 转:图解Git[强烈推荐]
https://my.oschina.net/xdev/blog/114383 再次感谢原著作者和中文翻译者. 此页图解git中的最常用命令.如果你稍微理解git的工作原理,这篇文章能够让你理解的更透 ...