IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 背包问题 [动态规划] (01完全多重混合) -> 正文阅读

[数据结构与算法]背包问题 [动态规划] (01完全多重混合)

0/1背包问题

1.状态函数

f [ i ] [ j ] = s f[i][j]=s f[i][j]=s:选完前面i个物品的时候,背包的体积是j,能够得到的最大的价值为s 。

2.答案

f [ N ] [ V ] f[N][V] f[N][V]

3.递推起点和边界

f [ i ] [ 0 ] = 0 , f [ 0 ] [ j ] = 0 f[i][0]=0,f[0][j]=0 f[i][0]=0,f[0][j]=0

4、状态转移方程(递推关系)

for(int i=1;i<=N;i++)//物品的下标
	for(int j=1;j<=V;j++)
		if(j<v[i])
			f[i][j]=f[i-1][j];
		else
			f[i][j]=max(f[i-1][j],w[i]+f[i-1][j-v[i]]);

法一:二维数组(从前往后推)

#include<bits/stdc++.h>

using namespace std;

int N,V;

int v[1000000],w[1000000];//v数组表示体积,w数组表示价值 

int f[10000][10000];

int main()
{
	cin>>V>>N;
	
	for(int i=1;i<=N;i++)
	{
		cin>>v[i];
		cin>>w[i];
	}
	
	for(int i=1;i<=N;i++)
	{
		for(int j=1;j<=V;j++)
		{
			if(j<v[i])
			{
				f[i][j]=f[i-1][j];
			}
			else
			{
				f[i][j]=max(f[i-1][j],w[i]+f[i-1][j-v[i]]);
			}
		}
	}
	
	cout<<f[N][V];
	
	return 0;
}

法二:一维滚动数组(从前往后推)

f [ j ] f[j] f[j]012345678910
0013556891012
#include<bits/stdc++.h>

using namespace std;

int N,V;

int v[100000],w[100000];

int f[100000];

int main()
{
	cin>>V>>N;
	
	for(int i=1;i<=N;i++)
	{
		cin>>v[i];
		cin>>w[i];
	}
	
	for(int i=1;i<=N;i++)
	{
		for(int j=V;j>=v[i];j--)
		{
			f[j]=max(f[j],f[j-v[i]]);
		}
	}
	
	cout<<f[V];
	
	return 0;
}

完全背包

法一:二维数组(从前往后推)

#include<bits/stdc++.h>

using namespace std;

int V,N;

int v[100000],w[100000];

int f[10000][10000];

int main() 
{
	cin>>V>>N;
	
	for(int i=1;i<=N;i++)
	{
		cin>>v[i];
		cin>>w[i];
	}

	for(int i=1;i<=N;i++)
	{
		for(int j=1;j<=V;j++)
		{
			if(j<v[i])
			{
				f[i][j]=f[i-1][j];
			}
			else
			{
				f[i][j]=max(f[i-1][j],w[i]+f[i][j-v[i]]);
			}
		}
	}
	
	cout<<"max="<<f[N][V];
	
	return 0;
}

法二:一维滚动数组(从前往后推)

#include<bits/stdc++.h>

using namespace std;

int N,V;

int v[100000],w[100000];

int f[100000];

int main()
{
	cin>>V>>N;
	
	for(int i=1;i<=N;i++)
	{
		cin>>v[i];
		cin>>w[i];
	}
	
	for(int i=1;i<=N;i++)
	{
		for(int j=v[i];j<=V;j++)
		{
			f[j]=max(f[j],w[i]+f[j-v[i]]);
		}
	}
	
	cout<<"max="<<f[V];
	
	return 0;
}

多重背包

法一:视为多次0/1背包(一维滚动数组从后往前推)

#include<bits/stdc++.h>

using namespace std;

int N,V;

int v[100000],w[100000],s[100000];

int f[100000];

int main()
{
	cin>>V>>N;
	
	for(int i=1;i<=N;i++)
	{
		cin>>v[i];
		cin>>w[i];
		cin>>s[i];//拥有该物品的数量 
	}
	
	for(int i=1;i<=N;i++)//物品标号从1...n
	{
		for(int k=1;k<=s[i];k++)//第i个物品的数量,滚动s[i]次
		{
			for(int j=V;j>=v[i];j--)//从前往后推:s[i]次刷新,滚动,0/1背包
			{
				f[j]=max(f[j],f[j-v[i]]);
			}
		}
	}
	
	cout<<f[V];
	
	return 0;
}

法二:多件物品看成一个整体(一维滚动数组从后往前推)

#include<bits/stdc++.h>

using namespace std;

int N,V;

int v[100000],w[100000],s[100000];

int f[100000];

int main()
{
	cin>>V>>N;
	
	for(int i=1;i<=N;i++)
	{
		cin>>v[i];
		cin>>w[i];
		cin>>s[i];//拥有该物品的数量 
	}
	
	for(int i=1;i<=N;i++)
	{
		for(int j=V;j>=0;j--)
		{
			for(int k=0;k<=s[i];k++)
			{
				if(k*v[i]>j)
				{
					break;
				}
				else
				{
					f[j]=max(f[j],f[j-k*v[i]]+k*w[i]);
				}
			}
		}
	}
	
	cout<<f[V];
	
	return 0;
}

法三:二进制方法拆分为多件物品的组合(即成为了0/1背包)

拆分出来的每个大物品都是独一无二的(一维滚动数组从后往前推)

#include<bits/stdc++.h>

using namespace std;

int N,V;

int v[100000],w[100000],s[100000];

int f[100000];

int n;

int main()
{
	cin>>N>>V;
	
	int a,b,s;
	
	for(int i=1;i<=N;i++)
	{
		cin>>a>>b>>s;
		
		int k=1;
		
		while(k<s)
		{
			n++;
			
			v[n]=k*a;
			w[n]=k*b;
			
			s=s-k;
			
			k=k*2;	
		}	
		
		n++;
		
		v[n]=s*a;
		w[n]=s*b;
	}	
	
	for(int i=1;i<=N;i++)
	{
		for(int j=V;j>=v[i];j--)
		{
			f[j]=max(f[j],w[i]+f[j-v[i]]);
		}
	}
	
	cout<<f[V];
	
	return 0; 
} 

混合背包

一维滚动数组从后往前推

#include<bits/stdc++.h>

using namespace std;

int N,V;

int v[100000],w[100000],s[100000];

int f[100000];

int main()
{
	cin>>V>>N;
	
	for(int i=1;i<=N;i++)
	{
		cin>>v[i];
		cin>>w[i];
		cin>>s[i];
	}
	
	for(int i=1;i<=N;i++)
	{
		if(s[i]==0)
		{
			for(int j=v[i];j<=V;j++)//完全背包:从前往后推
			{
				f[j]=max(f[j],w[i]+f[j-v[i]]);//相同
			}
		}
		else
		{
			for(int k=1;k<=s[i];k++)//多重背包就是多个0/1背包的组合
			{
				for(int j=V;j>=v[i];j--)//0/1背包从后往前推
				{
					f[j]=max(f[j],w[i]+f[j-v[i]]);//相同
				}
			}
		}
	}
	
	cout<<f[V];
	
	return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:52:38  更:2022-09-21 00:57:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 13:09:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码