• 背包问题


    posted on 2019-08-27 19:16:24

    多重背包

    题目描述 Description

    你有一个容量为 (M) 的背包,和 (N) 种物品。

    每种物品都有三个属性,(v_i,w_i,c_i),分别表示这种物品的体积、价值和件数。

    你的任务是,从这些所给物品中,选出若干件,其体积之和不能超过背包容量,并且使所选物品的权值的和最大。

    输入描述 Input Description

    第一行两个整数(N,M)

    接下来 (N) 行每行三个数(v_i,w_i,c_i)描述第 (i) 件物品的属性

    输出描述 Output Description

    最大的权值和

    样例输入 Sample Input

    2 8
    2 100 4
    4 100 2
    

    样例输出 Sample Output

    400
    

    数据范围及提示 Data Size & Hint

    对于20%的数据,(c_i=1)

    对于60%的数据,(N,M leq 500,c_i leq 100)

    对于90%的数据,(N,M leq 3000)

    对于100%的数据 , (N,M leq 7000,c_i leq 5000),保证答案不超过 (2147483647)

    • tip:

    • 有多重背包的题目,数组一定要开大!!!!!!

    • 不然会 WA 而不是 RE .

    题解1:

    int n,m,tot;
    int f[7010],p[100010],v[100010],w[100010];
    int main()
    {
    	cin >> n >> m;
    	for(int i=1; i<=n; i++)
    		cin >> w[i] >> v[i] >> p[i];
    	for(int i = 1; i <= n; i++) {
    		int num = min(p[i], m / w[i]);
    		for(int k = 1; num > 0; k <<= 1) {
    			if (k > num) k = num;
    			num -= k;
    			for(int j = m; j >= w[i] * k; j--)
    				f[j] = max(f[j], f[j - w[i] * k] + v[i] * k);
    		}
    	}
    	cout << f[m];
    

    题解2:

    int n,m,tot;
    int f[7010],c[100010],v[100010];
    int main() 
    {
    	cin >> n >> m;
    	for(int i=1;i<=n;i++) {
    		int x,y,z;
    		cin >> x >> y >> z;
    		int base=1;
    		while(z>=base) {
    			c[++tot]=x*base;
    			v[tot]=y*base;
    			z-=base;
    			base<<=1;
    		}
    		if(z>0) {
    			c[++tot]=z*x;
    			v[tot]=z*y;
    		}
    	}
    	for(int i=1;i<=tot;i++)
    		for(int j=m;j>=c[i];j--)
    			f[j]=max(f[j],f[j-c[i]]+v[i]);
    	cout << f[m];
    

    混合背包

    题目描述

    (n) 种物品和一个容量是 (m) 的背包。

    物品一共有三类:

    • 第一类物品只能用 (1) 次((01) 背包);
    • 第二类物品可以用无限次(完全背包);
    • 第三类物品最多只能用 (s_i) 次(多重背包)。

    每种物品体积是 (w_i),价值是 (v_i)。求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。输出最大价值。

    输入格式

    从标准输入读入数据。

    第一行两个整数 (n)(m)(0 leq v_i,w_i leq 1000)),用空格隔开,分别表示物品种数和背包容积。

    接下来有 (n) 行,每行三个整数 (w_i,v_i)(0 leq w_i,v_i leq 1000))和 (s_i)(-1 leq s_i leq 1000)),用空格隔开,分别表示第 (i) 种物品的体积、价值和数量。

    • (s_i = -1) 表示第 (i) 种物品只能用 (1) 次;
    • (s_i = 0) 表示第 (i) 种物品可以用无限次;
    • (s_i > 0) 表示第 (i) 种物品可以使用 (s_i) 次。

    输出格式

    输出到标准输出。

    输出一个整数,表示最大价值。

    样例1输入

    4 5
    1 2 -1
    2 4 1
    3 4 0
    4 5 2
    

    样例1输出

    8
    

    题解:

    int n,m,v[10000],w[10000],s[10000],a,b,c,f[10000];
    int main()
    {
    	int num=1;
    	cin >> n >> m;
    	for(int i=1;i<=n;i++)
    	{
    		cin >> a >> b >> c;
    		if(c>0)
    		{
    			int base = 1;
    			while(c>=base)
    			{
    				w[num]=a*base;
    				v[num]=b*base;
    				s[num++]=-1;
    				c-=base;
    				base*=2;
    			}
    			if(c>0)
    			{
    				w[num]=a*c;
    				v[num]=b*c;
    				s[num++]=-1;
    			}
    		}
    		else
    		{
    			w[num]=a;
    			v[num]=b;
    			s[num++]=c;
    		}
    	}
    	for(int i=1;i<=num-1;i++)
    	{
    		if(s[i]==0)
    		{
    			for(int j=w[i];j<=m;j++)
    				f[j]=max(f[j-w[i]]+v[i],f[j]);
    		}
    		else 
    		{
    			for(int j=m;j>=w[i];j--)
    				f[j]=max(f[j-w[i]]+v[i],f[j]);
    		}
    	}
    	cout << f[m];
    
  • 相关阅读:
    React native 之 图标库ECharts的使用
    使用jquery给html标签加点击事件
    React native 之 async/await
    CSS布局之flexbox
    Swiper 的引入
    给浏览器设置一张背景图,并且拉动浏览器大小时图片不要被压缩变形
    境界的彼方_lduoj_bfs宽搜
    2021美国大学生数学建模大赛==ABCDEF+思路解析==
    3045 Lcm与Gcd构造
    对拍程序
  • 原文地址:https://www.cnblogs.com/xuanfly/p/11802930.html
Copyright © 2020-2023  润新知