初学DP
来源:互联网 发布:什么是网络在线客服 编辑:程序博客网 时间:2024/06/13 13:19
最开始遇到的第一个问题那就是最经典的 0 1 背包问题
上来先是用递归的暴力搜索引出来的,但是看了书上的代码,我觉得有必要重新看一下搜索的问题了
题目大意:从n个物品中选出总重量不超过m的最大价值
输出 n = 4,m = 5
(w,v) = {{2,3},{1,2},{3,4},{2,2}};
输出 7
#include <iostream>#define max(x,y) ((x)>(y)?(x):(y))using namespace std;int w[100];int v[100];int n,m;int rec(int i,int j)//搜索函数 ,i 表示当前是第几个背包,j表示不重量大于j的最大价值 {int res;//定义一个 返回值 if(i==n)//如果到最后一个,返回价值0 res = 0;else if(j<w[i])// 如果当前重量大于j 跳过当前 res = rec(i+1,j);else res = max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);//这就是关键一步,取二者的较大值,如果选取了当前物品的话,就要在递归完成后出的来的时候加上当前物品的价值,我说的你肯定也不好理解,还是多看多敲代码 return res;}/* 还有更简洁的写法,也是好多nb代码的样子那样,我现在觉得写成那样的不一定就是大牛,它也许就是想装B,让你看不懂int rec(int i,int j){if(i==n)return 0;else if(j<w[i])return rec(i+1,j);else return max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);} 这样是不是很牛X的样子呢??其实都j8一个道理,就是tm看着帅, */ int main(){cin>>n>>m;//n 表示有多少个物品,m表示最大体积,我并不是在做题,所以并没有写多组测试数据 for(int i=0;i<n;i++){cin>>w[i]>>v[i];}cout<<rec(0,m)<<endl;}
但是这种暴力递归效率很低,只要没到达出口,它就会一直递归下去,而且不管是否重复过(递归重复这个概念很容易理解,就比如在整数划分中 3 1 1 和1 3 1 是同一种情况),而DP它唯一的不同就是多用了一个DP数组来记录每一步运算的结果,并在每一次的循环之前先判断一下是否重复计算,如果重复了,直接把前面的值给取出来用就好了,说了这么一大堆废话,其实道理很简单,可就是想不到啊。。。。
下面是上面的升级版本---就是传说中的dp了
#include <iostream>#include <cstring>#define max(x,y) ((x)>(y)?(x):(y))using namespace std;int w[100];int v[100];int dp[110][110]; int n,m;int rec(int i,int j){if(dp[i][j]>=0)//如果这个值我们已经计算过了,那就直接那来用 return dp[i][j];int res;if(i==n)//到达结尾,返回0; res = 0;else if(j<w[i])//不满足重量,跳过 res = rec(i+1,j);else res = max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);//取较大值dp[i][j] = res;//这里区别上面的就是我们每次是记录结果,而不是返回结果 }/* ZB写法 int rec(int i,int j){if(dp[i][j]>=0)return dp[i][j];if(i==n)dp[i][j] = 0;else if(j<w[i])dp[i][j] = rec(i+1,j);else dp[i][j] = max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);}*/int main(){cin>>n>>m;memset(dp,-1,sizeof(dp));for(int i=0;i<n;i++){cin>>w[i]>>v[i];}rec(0,m);/*for(int i=0;i<n;i++)//这个循环可以输出我们记录的所以情况对理解很有帮助 {for(int j=0;j<=m;j++){cout<<"dp["<<i<<"]"<<"["<<j<<"]"<<"="<<dp[i][j]<<" ";}cout<<endl;}*/cout<<dp[0][m]<<endl;//这里输出对应的数组位置 return 0;}
接下来就是非递归的写法了
#include <iostream>#define max(x,y) ((x)>(y)?(x):(y))using namespace std;int dp[110][110];int w[110],v[110];int main(){int m,n;while(cin>>n>>m){int i,j;for(i=0;i<n;i++)cin>>w[i]>>v[i];for(i=0;i<=n;i++){for(j=0;j<=m;j++){if(j<w[i])//如果当前 j 小于 w[i] 就跳过当前物品 dp[i+1][j] = dp[i][j];else dp[i+1][j] = max(dp[i][j],dp[i][j-w[i]]+v[i]);//下一个的值等于 跳过上一个或者选取上一个中的最大值 }}cout<<dp[n][m]<<endl;}return 0;}
讲道理还是有点似懂非懂,太菜怪我咯。。。
0 0
- 初学DP
- hdu2089 初学数位dp
- 初学数位DP
- 概率DP初学整合
- 初学数位DP--hdu 2089
- 初学dp,资源分配实现
- hdu 2089(初学数位DP)
- UVA 11270 Tiling Dominoes 初学插头DP
- hdu 3555 Bomb(数位dp初学)
- 【DP算法篇之初学】背包问题
- HDU 1074 Doing Homework (状压+DP) 初学dp笔记
- 【DP算法篇之初学】LIS\LCS\二维DP\带条件DP
- 初学DP(1) 黑书中的《括号序列》
- 初学DP(2) 黑书中的《棋盘分割》
- 1---处女篇----初学dp,找的代码--------硬币数目
- 初学...
- 初学
- 初学
- IP地址详解
- Spring
- 列表操作
- Java (while结构)
- Spring02
- 初学DP
- web框架学习前复习——xml(1)
- Face Detection with the Faster R-CNN(数据集标注对比研究报告 )
- Java容器三:HashMap
- RoboCup中使用Gazebo和ROS
- android 压缩和解压文件
- 【codevs 3538】奇怪的函数
- Shiro——shiro架构
- IOS Dev Intro - IOS Interview QAs