poj 3666 Making the Grade (动态规划)
来源:互联网 发布:贫困 知乎 编辑:程序博客网 时间:2024/06/01 10:38
题目链接;
题目大意:
给定一个序列,以最小代价将其变成单调不增或单调不减序列,这里的代价看题目公式。
(但是我看网上的代码均是将其变成单调不减序列 )
思路:DP
用dp[i][j]表示:前i个数构成的序列,这个序列最大值为j,dp[i][j]的值代表相应的cost。
所以状态转移方程如下:
dp[i][j]=abs(a[i]-b[j])+min(dp[i-1][k]);(k<=j)
这个表格是根据转移方程写出来的dp数组。
再仔细看一下转移方程:dp[i][j]=abs(a[i]-b[j])+min(dp[i-1][k]);(k<=j)
右边没填充的是因为填充的数字肯定比前面的数字大,无用,因为在求min( dp[i-1][k] )时,是求最小值,既然更大,则最小值时无需考虑。
又从表格中可以看出:dp[i][j]=abs(a[i]-b[j])+min(dp[i-1][k]);(k<=j)这里的k无需从1遍历到j。
只要在对j进行for循环的时候不断更新一个dp[i-1][j]的最小值mine=min(mine,dp[i-1][j]),
然后对dp[i][j]=abs(a[i]-b[j])+mine;即可;
这样改进之后即可从本来的时候时间复杂度O(NMM)改进为O(NM);
但是,这里的m是A[i]的最大值,显然TLE。
所以必须用离散化思想改进,因为N=2000。远小于A[i]的最大值。
离散化:将序列排序一下,然后用位置的前后关系来制定其值,这样时间复杂度变成O(N^2).
#include <stdio.h>#include <algorithm>#include <iostream>#include <string.h>using namespace std;#define maxn 2200long long dp[maxn][maxn];int a[maxn],b[maxn];int n;void solve(){memset(dp,0,sizeof dp);for(int i=1;i<=n;i++){long long mine=dp[i-1][1];for(int j=1;j<=n;j++){mine=min(mine,dp[i-1][j]);dp[i][j]+=abs(a[i]-b[j])+mine;}}long long ans=dp[n][1];for(int i=1;i<=n;i++)ans=min(ans,dp[n][i]);printf("%lld\n",ans);}int main(){while(~scanf("%d",&n)){for(int i=1;i<=n;i++){scanf("%d",&a[i]);b[i]=a[i];}sort(b+1,b+1+n);solve();} return 0;}
我们发现可知,二维dp每次只用当前行和上一行,所以没必要开二维数组,开一个一维数组dp记录当前行,一个一维数组pre记录上一行
#include <stdio.h>#include <algorithm>#include <iostream>#include <string.h>using namespace std;#define maxn 2200long long dp[maxn],pre[maxn];int a[maxn],b[maxn];int n;void solve(){memset(dp,0,sizeof dp);memset(pre,0,sizeof pre);for(int i=1;i<=n;i++){long long mine=pre[1];for(int j=1;j<=n;j++){mine=min(mine,pre[j]);dp[j]=abs(a[i]-b[j])+mine;pre[j]=dp[j];}}long long ans=dp[1];for(int i=1;i<=n;i++)ans=min(ans,dp[i]);printf("%lld\n",ans);}int main(){while(~scanf("%d",&n)){for(int i=1;i<=n;i++){scanf("%d",&a[i]);b[i]=a[i];}sort(b+1,b+1+n);solve();} return 0;}
阅读全文
0 0
- poj 3666 Making the Grade (动态规划)
- 动态规划-POJ 3666 Making the Grade
- poj 3666 Making the Grade (动态规划)
- POJ 3666 Making the Grade(动态规划)
- poj 3666 Making the Grade (动态规划)
- poj 3666 Making the Grade 动态规划+滚动数组
- poj 3666 Making the Grade (离散化+动态规划)
- 动态规划 Making the Grade
- 动态规划训练23 [Making the Grade POJ
- POJ 3666 Making the Grade(左偏树)
- POJ 3666 Making the Grade (dp)
- POJ 3666--Making the Grade(dp)
- POJ 3666 Making the Grade(DP)
- POJ 3666 Making the Grade
- POJ 3666 Making the Grade
- POJ 3666 Making the Grade
- poj 3666--Making the Grade
- POJ 3666 Making the Grade
- MySQL的常用函数
- 最全面的Java多线程用法解析
- unity简单封装的网络请求
- ubuntu一键安装vnc脚本
- 获取版本信息(名称+版本号等)
- poj 3666 Making the Grade (动态规划)
- LeNet网络详解
- JavaScript运行机制之事件循环(Event Loop)详解
- 使用AIDL跨APP进行通信
- tftp配置
- 欢迎使用CSDN-markdown编辑器
- android ble 的各种坑
- PS人物快速换装--纯色换成碎花装
- JVM调优参数