几个简单的背包问题
来源:互联网 发布:刷脸开机软件 编辑:程序博客网 时间:2024/06/11 14:54
0/1背包问题,就是给n种石头每块石头的价值为ai,问背包容量为m的背包最多装价值多少?
输入样例:
3 8
2 5 5
3 4 5
输出:8
因为不能重复选,所以这次价格的的最大应该是dp[i-1]
#include<iostream>#include<string.h>#include <stdio.h>using namespace std;int dp[500][500];int cost[500];int weight[500];int main(){ freopen("in.txt","r",stdin); int i,j,k,l,f1,f2,f3,t1,t2,t3,n,m; cin >> n >> m; memset(weight,0,sizeof(weight)); memset(cost,0,sizeof(cost)); memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++){ cin >> weight[i]; } for(i=1;i<=n;i++){ cin >> cost[i]; } for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ if(j>=weight[i]) dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+cost[i]); else dp[i][j]=dp[i-1][j]; //cout << dp[i][j] << " "; } //cout << endl; } cout << dp[n][m] << endl;}完全背包问题:就是有n种石头无限多个,每个的重量为a价值为bii,问背包为m的背包最多装价值多少的石头
输入样例
5 356 8
2 4
3 9
4 3
5 6
输出 103
因为能重复选,所以这次价格的的最大应该是max(dp[i-1][j],dp[i][j-weight[i]]+cost[i])!!注意原来是dp[i-1][j]
#include<iostream>#include<string.h>#include <stdio.h>using namespace std;int dp[500][500];int cost[500];int weight[500];int main(){ freopen("in.txt","r",stdin); int i,j,k,l,f1,f2,f3,t1,t2,t3,n,m; cin >> n >> m; memset(weight,0,sizeof(weight)); memset(cost,0,sizeof(cost)); memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++){ cin >> weight[i] >>cost[i]; } for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ if(j>=weight[i]) dp[i][j]=max(dp[i-1][j],dp[i][j-weight[i]]+cost[i]); else dp[i][j]=dp[i-1][j]; // cout << dp[i][j] << " "; } // cout << endl; } cout << dp[n][m] << endl;多重背包问题:
有N个石头,每个有ai个,价值分别为bi,重量为ci,问M的背包最多装多少价值?
输入样例:
10 20
2 100 4
4 100 2
5 100 6
6 100 8
10 100 5
20 100 2
15 50 3
12 60 4
11 80 6
20 90 5
输出:600
用0/1背包的问题,一个石头多种的就分别当作不同的石头,o(N*a[i])
#include<iostream>#include<string.h>#include <stdio.h>using namespace std;int dp[500][500];int value[500];int weight[500];int ds[500];int main(){ freopen("in.txt","r",stdin); int i,j,k,l,f1,f2,f3,t1,t2,t3,n,m; cin >> n >> m; memset(weight,0,sizeof(weight)); memset(value,0,sizeof(value)); memset(ds,0,sizeof(ds)); memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++){ cin >> weight[i] >> value[i] >> ds[i]; } t1=0; for(i=1;i<=n;i++){ for(k=1;k<=ds[i];k++){ t1++; for(j=1;j<=m;j++){ if(j>=weight[i]) dp[t1][j]=max(dp[t1-1][j],dp[t1-1][j-weight[i]]+value[i]); else dp[t1][j]=dp[t1-1][j]; //cout << dp[t1][j] << " "; } //cout << endl; } } cout << dp[t1][m] << endl;}用二进制加速
如一块石头有18个,因为是1个个加到dp[i][j]的j上,速度很慢,如果将其分为1、2、4、8、4那么这5个数字的组合是可以得到1-18的任意数的,也就是可以把18个石头变成5种石头,背包的1-m重量加这5个石头或者18个石头一个个加的意义是一样的。
这样的复杂度变成O(N*loga[i])
#include<iostream>#include<string.h>#include <stdio.h>#include<math.h>using namespace std;int dp[500][500];int value[500];int weight[500];int ds[500];int ds2[500];int main(){ freopen("in.txt","r",stdin); int i,j,k,l,f1,f2,f3,t1,t2,t3,n,m; cin >> n >> m; memset(weight,0,sizeof(weight)); memset(value,0,sizeof(value)); memset(ds,0,sizeof(ds)); memset(dp,0,sizeof(dp)); memset(ds2,0,sizeof(ds2)); for(i=1;i<=n;i++){ cin >> weight[i] >> value[i] >> ds[i]; } for(i=1;i<=n;i++){ t1=ds[i]; k=0; // cout <<t1 << " "; while(t1){ k++; ds2[k]=pow(2,k-1); t1-=ds2[k]; if(t1<pow(2,k)){ k++; ds2[k]=pow(2,k-1); break; } } // cout << k << endl; ds[i]=k; } t1=0; for(i=1;i<=n;i++){ for(k=1;k<=ds[i];k++){ t1++; for(j=1;j<=m;j++){ if(j>=ds2[k]*weight[i]) dp[t1][j]=max(dp[t1-1][j],dp[t1-1][j-ds2[k]*weight[i]]+ds2[k]*value[i]); else dp[t1][j]=dp[t1-1][j]; //cout << dp[t1][j] << " "; } //cout << endl; } } cout << dp[t1][m] << endl;}
0 0
- 几个简单的背包问题
- 几个背包问题的总结
- 简单的背包问题
- 简单的背包问题
- 简单的背包问题
- 简单的背包问题
- 简单的背包问题
- 简单的背包问题
- 简单的背包问题
- 一个简单的背包问题
- 最简单的背包问题
- 简单易懂的背包问题
- QT的几个简单问题
- 前端的几个简单问题
- 多线程的几个简单问题
- 简单的背包问题--java递归实现
- 简单的0-1背包问题
- 简单的01背包问题(采药)
- Unity 简易读取配置文件内容(txt,懒人用)
- 水平居中
- gulp基本用法
- Myeclipse 启动Tomcat时出现class file editor
- JavaScript闭包--学习总结
- 几个简单的背包问题
- GitHub上好用的开源库
- 2005年浙江大学计算机及软件工程研究生机试真题并查集UnionFindjava实现
- 详谈内存管理技术
- p12文件中导出公钥和私钥
- Java中的String类常量池详解
- MongoDbHelper
- Qt中如何将char*转LPCWSTR
- DateConverter