今天看了看背包九讲,自己写了下0-1背包和完全背包
王晓东《计算机算法分析与设计》上面给出的C++实现比较繁琐,相比而言这个版本更加简明
给出了测试数据
0-1背包问题C++实现
[cpp]
view plain
copy
- /*任务:计算0-1背包问题的最大价值
- Sample Input
- 10 4
- 2 1
- 3 3
- 4 5
- 7 9
- Sample Output
- 12
- 0 1 0 1
- */
- #include<stdio.h>
- #include<string.h>
- int c[20][1000];//c[k][y]为只允许装前k种物品,背包总重量不超过y的最大价值
- int inumber[21][1000];//inumber[k][u]为只允许装前K种物品,背包总重量不超过y时得到最大价值时使用的背包的最大标号
- int w[21],p[21];
- int knapsack(int m,int n)
- {
- int i,j;
- for(i=1;i<n+1;i++)
- scanf(“%d%d”,&w[i],&p[i]);
- memset(c,0,sizeof(c));
- memset(inumber,0,sizeof(inumber));
- for(j=1;j<m+1;j++){
- c[1][j]=j/w[1]*p[1];
- }
- for(i=1;i<n+1;i++){
- for(j=1;j<m+1;j++){
- if(j >= w[i]){
- if(p[i]+c[i-1][j-w[i]]>=c[i-1][j]){
- c[i][j]=p[i]+c[i-1][j-w[i]];
- inumber[i][j]=i;
- }
- else{
- c[i][j]=c[i-1][j];
- inumber[i][j]=inumber[i-1][j];
- }
- }
- else{
- c[i][j]=c[i-1][j];
- inumber[i][j]=inumber[i-1][j];
- }
- }
- }
- return(c[n][m]);
- }
- void trackSolution(int m, int n){
- int x[21];
- int y = m;
- int j = n;
- memset(x, 0, sizeof(x));
- while(true){
- j = inumber[j][y];
- x[j] = 1;
- y = y – w[j];
- while(inumber[j][y] == j){
- y = y – w[j];
- x[j]++;
- }
- if(!inumber[j][y]) break;
- }
- printf(“最大价值方案中各个物品的个数为(物品标号从1到n):”);
- for(j = 1; j <= n; j++){
- printf(“%d “, x[j]);
- }
- printf(“\n”);
- }
- int main()
- {
- int m,n;
- while(scanf(“%d%d”,&m,&n)!=EOF){
- printf(“最大价值为%d\n”,knapsack(m,n));
- trackSolution(m, n);
- }
- return 0;
- }
完全背包问题C++实现
[cpp]
view plain
copy
- /*任务:计算完全背包问题的最大价值
- Sample Input
- 10 4
- 2 1
- 3 3
- 4 5
- 1 9
- Sample Output
- 90
- 0 0 0 10
- */
- #include<stdio.h>
- #include<string.h>
- int c[20][1000];//c[k][y]为只允许装前k种物品,背包总重量不超过y的最大价值
- int inumber[21][1000];//inumber[k][u]为只允许装前K种物品,h背包总重量不超过y时得到最大价值时使用的背包的最大标号
- int w[21],p[21];
- int knapsack(int m,int n)
- {
- int i,j;
- for(i=1;i<n+1;i++)
- scanf(“%d%d”,&w[i],&p[i]);
- memset(c,0,sizeof(c));
- memset(inumber,0,sizeof(inumber));
- for(j=1;j<m+1;j++){
- c[1][j]=j/w[1]*p[1];
- }
- for(i=1;i<n+1;i++){
- for(j=1;j<m+1;j++){
- if(j >= w[i]){
- if(p[i]+c[i][j-w[i]]>=c[i-1][j]){//和0-1背包相比只是将c[i-1][j-w[i]]写成了c[i][j-w[i]],因为完全背包问题中每件物品有无限个
- c[i][j]=p[i]+c[i][j-w[i]];
- inumber[i][j]=i;
- }
- else{
- c[i][j]=c[i-1][j];
- inumber[i][j]=inumber[i-1][j];
- }
- }
- else{
- c[i][j]=c[i-1][j];
- inumber[i][j]=inumber[i-1][j];
- }
- }
- }
- return(c[n][m]);
- }
- void trackSolution(int m, int n){
- int x[21];
- int y = m;
- int j = n;
- memset(x, 0, sizeof(x));
- while(true){
- j = inumber[j][y];
- x[j] = 1;
- y = y – w[j];
- while(inumber[j][y] == j){
- y = y – w[j];
- x[j]++;
- }
- if(!inumber[j][y]) break;
- }
- printf(“最大价值方案中各个物品的个数为(物品标号从1到n):”);
- for(j = 1; j <= n; j++){
- printf(“%d “, x[j]);
- }
- printf(“\n”);
- }
- int main()
- {
- int m,n;
- while(scanf(“%d%d”,&m,&n)!=EOF){
- printf(“最大价值为%d\n”,knapsack(m,n));
- trackSolution(m, n);
- }
- return 0;
- }