动态规划--01背包模型

01背包剖析

问题引入

题目来源:ACwing:01背包问题

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。第 i 件物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。

输入格式

第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式

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

数据范围

0<N,V≤1000

0<vi,wi≤1000

输入样例

4 5
1 2
2 4
3 4
4 5

输出样例:

8

搜索代码

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
const int N = 1005;

int f[N][N], w[N] , v[N] , n , m;

// x 代表i件 物品
// y 代表当前最大容量
int dfs(int x,int y)
{
	if(f[x][y] != -1)return f[x][y];
	int ans = 0;
	if(x == 0)return 0;
	if(y >= w[x])
	{
		ans = max(dfs(x - 1, y) ,dfs(x - 1, y - w[x]) + v[x]);
	}else ans = dfs(x - 1, y);
	return f[x][y] = ans;
}
int main()
{
	fill(f[0],f[0] + N * N , -1);
	cin >> n >> m;
	for(int i = 1; i <= n ;i ++)
	{
		cin >> w[i] >> v[i];
	}
	cout << dfs(n, m) << endl;
	return 0;
}

虽然记忆化搜索的方式已经大大的优化了代码但是远远没有达到动态规划的\(O(VN)\)级别的复杂度

引入01背包问题的动态规划方式

和记忆化搜索一样我们依旧将问题分割考虑在背包容量为 j 的情况的下从前i个物品中能取得的最大价值

定义 : f[i][j] : 表示该状态

由于每件物品只有放和不放两种状态

放: f[i][j] = max(f[i-1][j],f[i-1][j-w[i]] + v[i])

不放:f[i-1][j] = f[i-1][j]

故根据以上状态转移方程我们可以得出下表

dp代码

#include <iostream>![](https://img2020.cnblogs.com/blog/1670159/202004/1670159-20200405125006679-936001362.png)

#include <algorithm>
#include <string>
using namespace std;
const int N = 1005;
int  v[N],w[N],f[N][N];
int main()
{
	int n , m;
	cin >> n >> m;
	for(int i = 1;i <= n;i ++)cin >> v[i] >> w[i];

	for(int i = 1;i <= n;i ++)
	{
		for(int j = 0; j <= m; j++)
		{
			f[i][j] = f[i - 1][j];
			if(j >= v[i])f[i][j] = max(f[i][j],f[i-1][j - v[i]] + w[i]);
		}
	}
	cout << f[n][m];
	return 0;
} 

一维优化

通过观察我们可以发现我们的每一次的状态都仅由当前状态的前一层状态转移而来 故我们可以只保留上一层状态

来优化我们的存储空间 这种优化又叫做滚动数组

但是要注意更新状态的时候要采用倒序循环。

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int N = 1005;
int  v[N],w[N],f[N];
int main()
{
	int n , m;
	cin >> n >> m;
	for(int i = 1;i <= n;i ++)cin >> v[i] >> w[i];
	for(int i = 1;i <= n;i ++)
	{
		for(int j = m; j >= v[i]; j--)
		{
			f[j] =  max(f[j-1],f[j-w[i]] + v[i]);
		}
	}
	cout << f[m];
	return 0;
}

最长上升子序列问题(LIS)

问题描述:acwing895.最长上升子序列

\(O(n^{2})解法 动态规划\)

使用f[i]表示从第一个数字开始算,以w[i]结尾的最大的上升序列。(以w[i]结尾的所有上升序列中属性为最大值的那一个)

if(w[i] > w[j])

f[i] = max(f[i],f[j]+1);

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
const int N = 10005;
int a[N] , f[N] , n ;
int main()
{
    cin >> n;
    for(int i = 1;i <= n ;i ++)scanf("%d",&a[i]);
    int ans = 0;
    f[0] = 0;
    for(int i = 1; i <= n ;i ++)
    {
        f[i] = 1;
        for(int j = 1;j < i;j ++)
        {
            if(a[i] > a[j])
            {
                f[i] = max(f[i],f[j] + 1);
            }
        }
        ans = max(f[i],ans);
    }
    cout << ans << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/wlw-x/p/12636743.html

时间: 2024-10-06 07:45:04

动态规划--01背包模型的相关文章

动态规划/0-1背包

每年毕业的季节都会有大量毕业生发起狂欢,好朋友们相约吃散伙饭,网络上称为"bg".参加不同团体的bg会有不同的感觉,我们可以用一个非负整数为每个bg定义一个"快乐度".现给定一个bg列表,上面列出每个bg的快乐度.持续长度.bg发起人的离校时间,请你安排一系列bg的时间使得自己可以获得最大的快乐度.    例如有4场bg:    第1场快乐度为5,持续1小时,发起人必须在1小时后离开:    第2场快乐度为10,持续2小时,发起人必须在3小时后离开:    第3场快

动态规划01背包记录

01背包是动态规划的一种类型其主要的形式是: 1.所有类型物品每种类型只有一个 2.一次只能取一个且物品不能分割 3.只有取或者不取(所以叫01背包,就是只有这两种情况) 4.在背包容量不满的前提下尽可能多的装入最大价值的物品 设背包的容量为V,第i个物品的重量为weigh[i]对应的价值为price[i];  设容量为j(j的最大值为背包的容量)的背包所能装的最大价值为dp[j] n为所有的物品个数,我们先从第1个数据开始,则此物品重量为weigh[1],则我们将所有大于weigh[1]的背包

[动态规划] 01背包与完全背包

01背包(每种物品的状态为选择或不选择,最多只能选1件): 1.传统的二维数组,第i件物品的重量为w[i],价值为v[i] dp[i][j]保存的是选择前i件物品(每一件物品的状态为选与不选),在背包容量为j的情况下,可以获得的最大价值 两种情况: 一.当前背包容量j<第i件的重量时,第i件背包肯定不能选,放不下去,有dp[i][j]=dp[i-1][j] 二.当前背包容量j>=第i件的重量时,第i件背包可以选,能放得下去,但因为要考虑到所获得最大价值,所以这时候有两种选择,选或不选,我们要在

动态规划-01背包

先认错,学长们很早之前就讲过了,然而我现在才来写... 01背包 01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2--Wn,与之相对应的价值为P1,P2--Pn. 01背包题目的雏形是: 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. 从这个题目中可以看出,01背包的特点就是:每种物品仅有一件,可以选择放或不放. 其状态转移方程是: f[i][v]=max{f[i-1][v],f[i-1][v-c

【算法学习笔记】30.动态规划 01背包和完全背包的关系

首先先说明一下01背包和完全背包问题的区别 01背包:有 N 件物品和一个容量为 V 的背包.放入第 i 件物品耗费的费用是 Ci,得到的价值是 Wi.求解将哪些物品装入背包可使价值总和最大.(可以不装满) 完全背包:有 N 种物品和一个容量为 V 的背包,每种物品都有无限件可用.放入第 i 种物品 的费用是 Ci,价值是 Wi.求解:将哪些物品装入背包,可使这些物品的耗费的费用总和不超过背包容量,且价值总和最大. 先说结论: 两个问题的最优解都要用DP来解决,实现的过程也非常像只是在内层循环中

动态规划——01背包

转 https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html 问题描述:有n 个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和? 三.动态规划的原理及过程: eg:number=4,capacity=8 i 1 2 3 4 w(体积) 2 3 4 5 v(价值) 3 4 5 6       定义V(i,j):当前背包容量 j,前 i 个物品最佳组合对应的价值:   寻找递推关系式,面对当

Poj1837 Balance 动态规划-01背包

Description Gigel has a strange "balance" and he wants to poise it. Actually, the device is different from any other ordinary balance. It orders two arms of negligible weight and each arm's length is 15. Some hooks are attached to these arms and

动态规划 01背包学习中

#include<iostream> #include<math.h> #include<stdio.h> using namespace std; //int ct=0; //int arr[1000]={0}; struct Bag{ int kg; int value; }; Bag sth[6]={0,0,2,6,2,3,6,5,5,4,4,6}; int bag[8][11]={0}; void dongtaiguihjua() { for(int i=5;i

HDU 1171 01背包

Big Event in HDU Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 28020    Accepted Submission(s): 9864 Problem Description Nowadays, we all know that Computer College is the biggest department