总算是有些发了狠,不能再摸下去了这里从dp开始,争取每天一篇+
这里直接以01背包为例01
一、dp是什么?
动态规划
看一步走一步,要的最多(bushi贪心)
二、使用步骤
1.状态表示
在本题中,我们要考虑在N个物品内选择不超过体积V的i件物品,
我们用v[i]来表示各物品体积,w[i]表示价值。那么,根据闫氏dp我们规定:
f[i][j]为前i件物品且体积不超过j的物品的价值,那么,我们求的就是
前N件物品且体积不超过V的价值f[N][V]
2.状态计算
对于f[i][j]我们考虑一下2种情况:
1.当j(我们给的体积)小于v[i]时第i件物品放不下
那么其递推公式为:f[i][j]=f[i-1][j]
因为放不下,体积不变
2.当j(我们给的体积)小于v[i]时第i件物品放得下
那么其递推公式为:f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i])
max第一个直接不放,第二个是放得下,但要退回第i-1个体积j-去第i个的体积再加w[i]
三.代码
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <iomanip>
//#include <bits/stdc++.h>
using namespace std;
int v[1001], w[1001];//体积,与 价值
int f[1001][1001];//前i项不超过体积v的价值
bool cmp(int a, int b)
{
return a > b;
}
int main()
{
int N, V;//输入N个,最大体积V
cin >> N >> V;
for (int i = 1; i <= N; i++)
{
cin >> v[i] >> w[i];
}
for (int i = 1; i <= N; i++)
{
for (int j = 0; j <= V; j++)
{
if (j < v[i])//如果此时给的体积小于v[i]的话,就放不进去
{
f[i][j] = f[i - 1][j];//所以此时第i项的价值等于第前i-1项的
}
else
{
//否则 不放第i个 放第i个
f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
}
}
}
cout << f[N][V];
return 0;
}
四.优化
观察易发现第i项用的都是第i-1项的
f[i][j] = f[i - 1][j];
f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
我们考虑删除为:
f[j] = f[j];
但是j-v[i]却用的还是第i项的,怎么变成第i-1项呢?用减法,具体见代码
f[j] = max(f[j], f[j - v[i]] + w[i]);
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int v[1001],w[1001],f[1001];
int main()
{
int N,V;
cin>>N>>V;
for(int i=1;i<=N;i++)
{
cin>>v[i]>>w[i];
}
for(int i=1;i<=N;i++)
for(int j=V;j>=1;j--)
{
if(j<v[i])
{
f[j]=f[j];
}
else
{
f[j]=max(f[j],f[j-v[i]]+w[i]);
}
}
cout<<f[V];
return 0;
}