zoukankan      html  css  js  c++  java
  • 背包问题

    背包问题

    来源

    完全基于中山纪念中学 宋新波ppt的一次复习

    动态规划的关键点

    • 最优化原理

    子问题最优化结构

    • 无后效性

    未来与过去无关

    • 状态

    描述最优解的结构

    • 状态转移方程

    递归定义最优解的值

    • 程序实现

    用记忆化搜索或迭代法求解

    No.1:01背包

    问题

    有N种物品和一个容量为V的背包。
    第i种物品只有1个,体积是v[i],价值是w[i]。
    选择物品装入背包使这些物品的体积总和不超过背包容量,且价值总和最大,求出这个最大价值。

    分析

    • 状态

      (f[i,j])表示用体积为j的背包装前i个物品能获得的最大价值。考虑第i种物品装或不装进行状态转移:

      (f[i-1,j-v[i]]+w[i])(必须满足(j>=v[i]))

      • 不装

      (f[i-1,j])

      • 两种情况取较大值。
    • 状态转移方程为:

    [f[i,j]=left{ egin{array}{rcl} 0 & &{i=0(边界条件)}\ f[i-1,j] & &{j<v[i]}\ max(f[i-1,j],f[i-1,j-v[i]]+w[i])& &{j>=v[i]}\ end{array} ight. ]

    • 答案为(f[n,v]),时间复杂度为(O(N*V))

    code

    #include <bits/stdc++.h> 
    using namespace std;
    
    const int Max=1e4+10;
    int w[Max],v[Max];
    int f[Max][Max]={0};
    
    int main()
    {
    	int n,m;
    	cin>>n>>m;
    	for(int i=1; i<=n; i++)	cin>>v[i];
    	for(int i=1; i<=n; i++)	cin>>w[i];
    	for(int i=1; i<=n; i++)
    		for(int j=0; j<=m; j++)
    			if(j<v[i])	f[i][j]=f[i-1][j];
    			else	f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
    	cout<<f[n][m]<<endl;
    	return 0;
    }
    

    No.2:完全背包

    问题

    有N种物品和一个容量为V的背包。
    第i种物品有无穷个,体积是v[i],价值是w[i]。
    选择物品装入背包使这些物品的体积总和不超过背包容量,且价值总和最大,求出这个最大价值。

    分析

    方法一

    • 状态:

    (f[i,j])表示用体积为j的背包装前i个物品能获得的最大价值。
    考虑第(i)个物品装几个来进行状态转移,假设装(x)个,(x)的范围为(0<=x<=j / v[i])

    • 状态转移方程:

    [f[i,j]=left{ egin{array}{rcl} 0 & &{i=0(边界条件)}\ max{f[i-1,j-x*v[i]]+x*w[i]}& &{0<=x<=j / v[i]}\ end{array} ight. ]

    • 答案为(f[n,v]),时间复杂度为(O(V^2*displaystyle sum^N_{i=1}{frac1{v[i]}}))

    code

    #include <bits/stdc++.h> 
    using namespace std;
    
    const int Max=1e4+10;
    int w[Max],v[Max];
    int f[Max][Max]={0};
    
    int main()
    {
    	int n,m;
    	cin>>n>>m;
    	for(int i=1; i<=n; i++)	cin>>v[i];
    	for(int i=1; i<=n; i++)	cin>>w[i];
    	for(int i=1; i<=n; i++)
    		for(int j=0; j<=m; j++)
    			for(int x=0; x<=j/v[i]; x++)
    				f[i][j]=max(f[i][j],f[i-1][j-x*v[i]]+x*w[i]);
    	cout<<f[n][m]<<endl;
    	return 0;
    }
    

    方法二

    • 状态

    (f[i,j])表示用体积为j的背包装前(i)个物品能获得的最大价值。

    • 考虑第(i)个物品装或不装来进行状态转移:
      • 装:

      必须满足(j>=v[i]),由于物品有无穷多个,装一次后后面还可以再装,所以状态为(f[i,j-v[i]]+w[i]);

      • 不装:

      (f[i-1,j])

    • 状态转移方程:

    [f[i,j]=left{ egin{array}{rcl} 0 & &{i=0(边界条件)}\ f[i-1,j] & &{j<v[i]}\ max(f[i-1,j],f[i,j-v[i]]+w[i]) & &{j>=v[i]}\ end{array} ight. ]

    • 答案为(f[n,v]),时间复杂度为(O(N*V))

    code

    #include <bits/stdc++.h> 
    using namespace std;
    
    const int Max=1e4+10;
    int w[Max],v[Max];
    int f[Max][Max]={0};
    
    int main()
    {
    	int n,m;
    	cin>>n>>m;
    	for(int i=1; i<=n; i++)	cin>>v[i];
    	for(int i=1; i<=n; i++)	cin>>w[i];
    	for(int i=1; i<=n; i++)
    		for(int j=0; j<=m; j++)
    			if(j<v[i])	f[i][j]=f[i-1][j];
    			else	f[i][j]=max(f[i-1][j],f[i][j-v[i]]+w[i]);
    	cout<<f[n][m]<<endl;
    	return 0;
    }
    

    No.3:多重背包(未完待续)

  • 相关阅读:
    Field 'id' doesn't have a default value错误解决方法
    jQuery:详解jQuery中的事件(一)
    Javascript:Javascript数据类型详解
    CSS:CSS样式表及选择器优先级总结
    Javascript:JSON总结
    CSS:CSS使用Tips
    Git:Git初体验——Git安装配置
    CSS:使用CSS媒体查询创建响应式布局
    多人操作sqlite3数据库冲突问题解决方法
    c++获取sqlite3数据库表中所有字段的方法
  • 原文地址:https://www.cnblogs.com/vasairg/p/12385336.html
Copyright © 2011-2022 走看看