《面试准备》c/c++动态规划解0-1背包、完全背包、多重背包问题

一、0-1背包

原始0-1背包问题描述:

给定n种物品,以及第i个物品的空间大小a[i]和价值c[i]。有一容量为V背包,问:应如何选择装入背包的物品,使得装入背包中物品的总价值最大?

输入:

一个整数V:背包的容量;

一个整数n:物品的个数;

第i个物品的空间大小a[i];

第i个物品价值c[i];

输出:

背包中物品最大总价值

举例:

输入:

10

3

2 5 4

5 7 10

输出:

17

c++代码实现(动态规划求解):

#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
int i,j,k,l,n,m;
int a[1000],b[1000],c[1000],f[1000];

int fun(int a[], int c[])
{
    for(i=1;i<=n;i++) {
		for(j=m;j>=a[i];j--) {
            if (f[j] < f[j - a[i]] + c[i])
                f[j] = f[j - a[i]] + c[i];
		}
	}
	return f[m];
}

int main()
{
    /**输入参数:
     * @param m 表示背包的最大容量
     * @param n 表示商品个数
     * @param a[] 每个商品的容量
     * @param c[] 每个商品的价值
     */
	cin>>m;
	cin>>n;
    for(i=1;i<=n;i++)
        cin>>a[i];
    for(i=1;i<=n;i++)
        cin>>c[i];
    /**求最大value函数*/
	cout<<fun(a,c)<<endl;
	return 0;
}

0-1背包延伸问题1:

描述:

给定n种物品,以及第i个物品的空间大小a[i]。有一容量为V背包,问:应如何选择装入背包的物品,使得装入背包剩余空间最小?

输入:

一个整数V:背包的容量;

一个整数n:物品的个数;

第i个物品的空间大小a[i];

输出:

一个整数:最小剩余空间

举例:

输入:

10

3

2 5 4

输出:

1

分析:

背包型动态规划,相当于背包容量和背包中物品价值二者相等的0-1背包问题。

c++代码实现(动态规划求解):

#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
int i,j,k,l,n,m;
int a[1000],b[1000],f[1000];

int fun(int a[])
{
    for(i=1;i<=n;i++) {
		for(j=m;j>=a[i];j--) {
            if (f[j] < f[j - a[i]] + a[i])
                f[j] = f[j - a[i]] + a[i];
		}
	}
	return f[m];
}

int main()
{
    /**输入参数:
     * @param m 表示背包的最大容量
     * @param n 表示商品个数
     * @param a[] 每个商品的容量
     */
	cin>>m;
	cin>>n;
    for(i=1;i<=n;i++)
        cin>>a[i];
    /**求最大value函数*/
	cout<<m-fun(a)<<endl;
	return 0;
}

0-1背包延伸问题2:

在原始基础上多加了一个限制条件,比如不超过最大质量。


/**
限定条件为两种的背包问题
*/
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
int i,j,k,l,n,m;
int a[1000],b[1000],c[1000],f[1000][1000];

void fun(int a[], int b[], int c[])
{
    for(i=1;i<=n;i++) {
		for(j=m;j>=a[i];j--) {
			for(l=k;l>=b[i];l--) {
				//if(j>=a[i]&&l>=b[i])
                    f[j][l]=max(f[j][l],f[j-a[i]][l-b[i]]+c[i]);
			}
		}
	}
}

int main()
{
	//memset(f,0,sizeof(f));
    /**输入参数:
     * @param m 表示背包的最大容量
     * @param k 表示背包的最大质量
     * @param n 表示商品个数
     * @param a[] 每个商品的容量
     * @param b[] 每个商品的质量
     * @param p[] 每个商品的价值
     */
	cin>>m>>k;
	cin>>n;
	//for(i=1;i<=n;i++)cin>>a[i]>>b[i]>>c[i];
    for(i=1;i<=n;i++)
        cin>>a[i];
    for(i=1;i<=n;i++)
        cin>>b[i];
    for(i=1;i<=n;i++)
        cin>>c[i];
    /**求最大value函数*/
    fun(a,b,c);
	cout<<f[m][k]<<endl;
	return 0;
}

二、完全背包

问题描述:

  完全背包:有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

代码:

#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
int i,j,k,l,n,m;
int a[1000],b[1000],c[1000],f[1000];

int fun(int a[], int c[])
{
    for(i=1;i<=n;i++) {
		for(j=a[i];j<=m;j++) {   //注意此处,与0-1背包不同,这里为顺序,0-1背包为逆序
            if (f[j] < f[j - a[i]] + c[i])
                f[j] = f[j - a[i]] + c[i];
		}
	}
	return f[m];
}

int main()
{
    /**输入参数:
     * @param m 表示背包的最大容量
     * @param n 表示商品个数
     * @param a[] 每个商品的容量
     * @param c[] 每个商品的价值
     */
	cin>>m;
	cin>>n;
    for(i=1;i<=n;i++)
        cin>>a[i];
    for(i=1;i<=n;i++)
        cin>>c[i];
    /**求最大value函数*/
	cout<<fun(a,c)<<endl;
	return 0;
}

三、多重背包

问题描述:   

  多重背包:有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

思路:转化为0-1背包问题。

代码:

#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
int i,j,n,m,z=1;
int a[1000],p[1000],c[1000],f[1000],a1[1000],c1[1000];

int fun(int a[], int c[])
{
    for(i=1;i<=z-1;i++) {
		for(j=m;j>=a[i];j--) {
            if (f[j] < f[j - a[i]] + c[i])
                f[j] = f[j - a[i]] + c[i];
		}
	}
	return f[m];
}

void convt(int a[],int p[], int c[]){
    for(i=1;i<=n;i++){
        for(j=1;j<=p[i];j++){
            a1[z] = a[i];
            c1[z] = c[i];
            z++;
        }
    }
}

int main()
{
    /**输入参数:
     * @param m 表示背包的最大容量
     * @param n 表示商品的类数
     * @param a[] 每类商品的容量
     * @param p[] 每类商品的数量
     * @param c[] 每类商品的价值
     */
	cin>>m;
	cin>>n;
    for(i=1;i<=n;i++)
        cin>>a[i];
    for(i=1;i<=n;i++)
        cin>>p[i];
    for(i=1;i<=n;i++)
        cin>>c[i];a
    /**转为0-1背包**/
    convt(a,p,c);
    /**求最大value函数*/
	cout<<fun(a1,c1)<<endl;
	return 0;
}

或者:

#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
int i,j,k,n,m;
int a[1000],p[1000],c[1000],f[1000];

int fun(int a[], int c[]){
    for(i=1;i<=n;i++) {
		for(j=m;j>=a[i];j--){
		    for(k=1;k<=p[i];k++){
                if(j<k*a[i])break;
                f[j] = max(f[j],f[j-k*a[i]]+k*c[i]);
		    }
		}
	}
	return f[m];
}

int main()
{
    /**输入参数:
     * @param m 表示背包的最大容量
     * @param n 表示商品的类数
     * @param a[] 每类商品的容量
     * @param p[] 每类商品的数量
     * @param c[] 每类商品的价值
     */
	cin>>m;
	cin>>n;
    for(i=1;i<=n;i++)
        cin>>a[i];
    for(i=1;i<=n;i++)
        cin>>p[i];
    for(i=1;i<=n;i++)
        cin>>c[i];
    /**求最大value函数*/
	cout<<fun(a,c)<<endl;
	return 0;
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值