【算法笔记】 简单二维DP(资源分配 最长公共子序列 区间DP)
2018-03-14 20:47
561 查看
1.资源分配类
要求资源分配的最大值,我们可以用二维数组f[i][j]来表示前i个公司得到j台机器后所得到的最大盈利值。
方程是:
f[i][j]=max(f[i][j],f[i-1][k]+a[i][j-k]);
我们要去枚举每一个i和j,因此用双重循环来解决,k表示第i个公司取的不取机器数,即1~i-1个公司取的机器数;f[i-1][k]表示前i-1个公司取k台机器的最大值,a[i][j-k]表示第i个公司取剩余的k台机器的利益,那么f[i-1][k]+a[i][j-k]表示的就是第i个公司不取k台机器所得到的最大值,当然,k也是用循环来枚举的。
emm.......
有点绕,毕竟我感觉资源分配的博客是我一直相要写的,却一直不知道要怎么表达,因此写的有点绕,也只能在方程的基础上解释一下方程的意义了,那么结合代码也许可以更好理解一些:
2.最长公共子序列
这个其实很简单,设f[i][j]为第一个序列到第i个点第二个序
4000
列到第j个点的这段区域内的最长公共子序列。
1.如果a[i]=b[j],也就是当前两个字母相等,那么f[i][j]=f[i-1][j-1];也就是i-1,j-1这一段的最大值加上新判断的点,很好理解吧!
2.如果a[i]!=b[j],f[i][j]=max{f[i][j-1],f[j][i-1]}.也就是向前面的序列寻找最大值。
代码如下:
3.区间DP-石子合并
根据题意,求的是整个区间的最大值,那么必然要求出更小区间的最大值,从而得到最大值。
因此,我们不妨设f[i][j]第i到j区间的合并的最小值,可以得出:
f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+cost[i][j]);
f[i][k]+f[k+1][j]表示1~k区间和k+1~区间的最优值,cost[i][j]表示合并i~j的花费,同样,资源分配理解后这道题目其实很好理解的
要求资源分配的最大值,我们可以用二维数组f[i][j]来表示前i个公司得到j台机器后所得到的最大盈利值。
方程是:
f[i][j]=max(f[i][j],f[i-1][k]+a[i][j-k]);
我们要去枚举每一个i和j,因此用双重循环来解决,k表示第i个公司取的不取机器数,即1~i-1个公司取的机器数;f[i-1][k]表示前i-1个公司取k台机器的最大值,a[i][j-k]表示第i个公司取剩余的k台机器的利益,那么f[i-1][k]+a[i][j-k]表示的就是第i个公司不取k台机器所得到的最大值,当然,k也是用循环来枚举的。
emm.......
有点绕,毕竟我感觉资源分配的博客是我一直相要写的,却一直不知道要怎么表达,因此写的有点绕,也只能在方程的基础上解释一下方程的意义了,那么结合代码也许可以更好理解一些:
#include<bits/stdc++.h> using namespace std; int a[1000][1000],f[1000][1000]={},n,m; int main() { cin>>m>>n; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) cin>>a[i][j]; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) for (int k=0;k<=j;k++) f[i][j]=max(f[i][j],f[i-1][k]+a[i][j-k]); cout<<f[n][m]; return 0; }
2.最长公共子序列
这个其实很简单,设f[i][j]为第一个序列到第i个点第二个序
4000
列到第j个点的这段区域内的最长公共子序列。
1.如果a[i]=b[j],也就是当前两个字母相等,那么f[i][j]=f[i-1][j-1];也就是i-1,j-1这一段的最大值加上新判断的点,很好理解吧!
2.如果a[i]!=b[j],f[i][j]=max{f[i][j-1],f[j][i-1]}.也就是向前面的序列寻找最大值。
代码如下:
#include<bits/stdc++.h> using namespace std; int f[6000][6000]={}; char a[100000],b[100000]; int main() { string sa,sb; cin>>sa>>sb; for (int i=0;i<sa.length();i++) a[i+1]=sa[i]; for (int j=0;j<sb.length();j++) b[j+1]=sb[j]; for (int i=1;i<=sa.length();i++) for (int j=1;j<=sb.length();j++) if (a[i]==b[j]) f[i][j]=f[i-1][j-1]+1; else f[i][j]=max(f[i-1][j],f[i][j-1]); cout<<f[sa.length()-1][sb.length()-1]; return 0; }
3.区间DP-石子合并
根据题意,求的是整个区间的最大值,那么必然要求出更小区间的最大值,从而得到最大值。
因此,我们不妨设f[i][j]第i到j区间的合并的最小值,可以得出:
f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+cost[i][j]);
f[i][k]+f[k+1][j]表示1~k区间和k+1~区间的最优值,cost[i][j]表示合并i~j的花费,同样,资源分配理解后这道题目其实很好理解的
#include<bits/stdc++.h> using namespace std; int n; int f[1000][1000]={}; int sum[1000]={}; int a[1000]={}; int cost[1000][1000]={}; int main() { cin>>n; for (int i=1;i<=n;i++) { cin>>a[i]; sum[i]=sum[i-1]+a[i];//前缀和 } for (int i=1;i<=n;i++) for (int j=i;j<=n;j++) cost[i][j]=sum[j]-sum[i-1]; for (int len=< b65e span class="sh_number" style="color:rgb(169,0,169);">1;len<=n;len++) for (int i=1;i<=n;i++) { int j=i+len-1; if (j>n) continue; for (int k=i;k<j;k++) if ((f[i][k]+f[k+1][j]+cost[i][j]<f[i][j])||!f[i][j]) f[i][j]=f[i][k]+f[k+1][j]+cost[i][j]; } cout<<f[1][n]; return 0; }
相关文章推荐
- 算法讲解之Dynamic Programing —— 背包DP [资源分配问题]
- 简单Dp----最长公共子序列,DAG最长路,简单区间DP等
- 【poj 3056】The Bavarian Beer Party (区间DP+最大匹配不交叉的简单算法)
- POJ-2155 简单二维线段树 区间翻转
- 【简单dp】poj 1458 最长公共子序列【O(n^2)】【模板】
- 算法笔记_070-BellmanFord算法简单介绍(Java)
- nullnulllinux动态异长存储资源分配算法的实现
- 简单dp算法——百炼02:滑雪
- 算法笔记-卡尔曼滤波器简单解释
- 机器分配(资源)dp
- 算法笔记_071:SPFA算法简单介绍(Java)
- 【算法学习笔记】67.状态压缩 DP SJTU OJ 1383 畅畅的牙签袋
- UVA10003---Cutting Sticks(简单区间dp)
- 算法提高 合并石子(区间dp,四边形不等式优化)
- 算法笔记_071-SPFA算法简单介绍(Java)
- 存储管理-分区分配与回收算法(Java简单实现)
- 【算法学习笔记】91.简单森林计数 SJTU OJ 1045 二哥的家族
- 【算法学习笔记】53.单调队列的简单应用 SJTU OJ 1034 二哥的金链
- 夕拾算法进阶篇:15)最长公共子序列(动态规划DP)
- HDU 6049 Sdjpx Is Happy 贪心 区间DP 从简单的情况着手思考