(难)POJ-3666 sort预处理+DP
2016-05-17 23:07
323 查看
题目大意:给定长为N的序列A1,
... , AN,将其变为B1,
. ... , BN,且序列B必须非严格单调,代价为|A1 - B1|
+ |A2 - B2|
+ ... + |AN - BN |,求最小代价。
题目链接:点击打开链接
分析:
首先,看解答前先知道两点。
1.这题数据水,求非严格递增的最小代价就行了
2.对于最终的B序列中的任意一个元素,一定在原来的A序列中可以找到。(网上看到的。。。)
在网上看到上面2点之后我尝试了一种很垃圾的做法:
dp[i][j]:表示前i个且b[i]的值取a[j]的Min
由于单增的限制,则b[i-1]<=b[i]=a[j],所以只需要枚举一遍a[],找出比a[j]小的a[k]来充当b[i-1]就行了,
于是 dp[i][j]=min(dp[i-1][k])+abs(a[j]-a[i]) 其中k满足a[k]<=a[j]
复杂度为O(n^3),裸上代码果断TLE了。。。于是又开始上网求助了。。。
然后我们还是
dp[i][j]:表示前i个且b[i]的值取a[j]的Min
由于我们会将j从1-n都取一遍,所有的a[j]都会尝试一遍并最终取Min,所以只要所有的a[j]都尝试一次就行了,至于尝试的顺序并不影响结果,所以我们索性将a[]按升序排列,为了保留下原始的数据,将a[]赋值给c[],然后将c[]排序,于是这时
dp[i][j]:表示前i个且b[i]的值取c[j]的Min
此时在求dp[i][j],我们肯定仍然要求出 min(dp[i-1][k]) 其中k满足c[k]<=c[j],即k<=j ,记为minn1
而在求dp[i][j+1],我们肯定仍然要求出 min(dp[i-1][k]) 其中k满足c[k]<=c[j+1],即k<=j+1,记为minn2,
我们发现 minn2=min(minn1,dp[i-1][j+1]),可以利用上次的结论,只要每次都更新当前的minn便好了,由此我们便可以省去求min(dp[i-1][k]) 的那层循环,
这时复杂度降为了O(n^2),毫无疑问可以AC了。
附上代码:
... , AN,将其变为B1,
. ... , BN,且序列B必须非严格单调,代价为|A1 - B1|
+ |A2 - B2|
+ ... + |AN - BN |,求最小代价。
题目链接:点击打开链接
分析:
首先,看解答前先知道两点。
1.这题数据水,求非严格递增的最小代价就行了
2.对于最终的B序列中的任意一个元素,一定在原来的A序列中可以找到。(网上看到的。。。)
在网上看到上面2点之后我尝试了一种很垃圾的做法:
dp[i][j]:表示前i个且b[i]的值取a[j]的Min
由于单增的限制,则b[i-1]<=b[i]=a[j],所以只需要枚举一遍a[],找出比a[j]小的a[k]来充当b[i-1]就行了,
于是 dp[i][j]=min(dp[i-1][k])+abs(a[j]-a[i]) 其中k满足a[k]<=a[j]
复杂度为O(n^3),裸上代码果断TLE了。。。于是又开始上网求助了。。。
然后我们还是
dp[i][j]:表示前i个且b[i]的值取a[j]的Min
由于我们会将j从1-n都取一遍,所有的a[j]都会尝试一遍并最终取Min,所以只要所有的a[j]都尝试一次就行了,至于尝试的顺序并不影响结果,所以我们索性将a[]按升序排列,为了保留下原始的数据,将a[]赋值给c[],然后将c[]排序,于是这时
dp[i][j]:表示前i个且b[i]的值取c[j]的Min
此时在求dp[i][j],我们肯定仍然要求出 min(dp[i-1][k]) 其中k满足c[k]<=c[j],即k<=j ,记为minn1
而在求dp[i][j+1],我们肯定仍然要求出 min(dp[i-1][k]) 其中k满足c[k]<=c[j+1],即k<=j+1,记为minn2,
我们发现 minn2=min(minn1,dp[i-1][j+1]),可以利用上次的结论,只要每次都更新当前的minn便好了,由此我们便可以省去求min(dp[i-1][k]) 的那层循环,
这时复杂度降为了O(n^2),毫无疑问可以AC了。
附上代码:
#include<iostream> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f int dp[2005]; int a[2005], c[2005]; int n, ans = INF; int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", a + i); memcpy(c, a, sizeof a); memset(dp, INF, sizeof dp); sort(c + 1, c + n + 1); for (int i = 1; i <= n; i++) dp[i] = abs(c[i] - a[1]); for (int i = 2; i <= n; i++) { int minn = INF; for (int j = 1; j <= n; j++) { minn = min(minn, dp[j]); dp[j] = minn + abs(c[j] - a[i]); } } for (int i = 1; i <= n; i++) ans = min(ans, dp[i]); printf("%d\n", ans); return 0; }
相关文章推荐
- Java Collection Framework 之 ArrayList 源码解析
- springMVC运行流程分析
- 设计模式之装饰设和代理设计模式
- python一些内建函数(map,zip,filter,reduce,yield等)
- 多周期CPU设计
- 产品思维学习(六)--浅谈产品数据分析
- 保持进程
- iOS收到推送后,跳转到某一页面
- 新手学习java一分钟了解Java核心技术
- Direct3D中 SetStreamSource 函数与数据流
- Markdown的使用简介
- LINUX SHELL控制结构while
- 软件项目开发流程图
- poj1273完全不懂为何过的dinic最大流模板
- android笔记(3)
- Android 侧滑面板的实现(DragLayout)
- GLSL学习资料整理
- 《jQuery从入门到精通》第一节 为什么要学习jQuery
- Codeforces Round #353 (Div. 2) D. Tree Construction __ Binary Search Tree
- 第1章 Web开发新时代