动态规划入门——背包问题
注意计算机的最大优点在于它的强大计算功能,以及存储功能,你能做的就是合理利用这些优点该循环就循环,该遍历就遍历。要知道简洁的算法毕竟不是那么多。
最基础、最重要、最好玩——01背包*
问题描述:
有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
例如:V=10 物品重量分别为 w[1]=3,w[2]=4,w[3]=6,w[4]=10,w[5]=8; 物品价格分别为V[1]=3,V[2]=3,V[3]=7,V[4]=9,V[5]=10;
## First
常规思维,太复杂。学要考虑的情况极其复杂,你可以试一下!!!!!
##Second
打表理解——————保证在计算背包时每一次将背包装到最优。
代码实现
状态转移方程 直接上一维 dp[j]=max(dp[j],dp[j-w[i]]+v[i]); ( j>=w[i] ) dp[j]——表示当背包容量为j时最优的价值 相当于是一次一次更新状态---->俗称状态转移方程。
#include<stdio.h>
#define max(a,b) a>b?a:b
int main()
{
int i,j,n=5,V=50;
int dp[100]={0},w[100],v[100];
for(i=0;i<n;i++)
scanf("%d%d",&w[i],&v[i]);
for(i=0;i<n;i++)
for(j=V;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
// dp[V]中就是最大值;
return0;
}
完全背包(背包问题的另一类问题)
问题描述:
一个背包,N种物品,每种物品的价值,所需空间;
求最优的解。。。。。。
一、打表理解。
二、状态转移方程:与01背包问题类似只是在第二重循环时括号内容会发生变化。
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
## 代码
#include<stdio.h>
#define max(a,b) a>b?a:b
int main()
{
int n,i,j,V;
int dp[100],w[100],v[100];
scanf("%d%d",&n,&V);
for(i=0;i<n;i++)
scanf("%d%d",&w[i],&v[i]);
for(i=0;i<n;i++)
for(j=w[i];j<=V;j++) //保证背包一次一次被遍历到;
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
//dp[V]即最优解;
return 0;
}
这是一篇高度浓缩的博客
完全背包一般包含两类问题:
1. 求背包恰好装满;
2. 可以不装满,只希望价格最大;
3. *********约束条件(分界线————是否玩转)
## 第一类问题
求背包能装的最小的价值且恰好能装满;
方法:
1,初始化dp[0]=0;
2, 初始化dp[1,2,3,…]为极小值;
结果判定
若dp[m]=INT (极小值) 则装不满 ?????不好理解 自己打表一目了然;
## 第二类问题
dp[0…m]=0;
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
多重背包(背包问题的另一形式)
问题描述:
有一个背包V内存,N种物品,每种物品w,v,N; 所需空间,价值,数量;
求最优解;
解释一下:
其实这就是升级版本的01背包问题,第i个物品有N个,不就可以算出一共有几个物品吗?
加一重循环就行
for(int i=0;i<n;i++)
for(int k=0;k<N[i];k++)
for(j=V;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
------------->但是这是一种费事的方法,价值不大;
## 核心(二进制优化)
将一个数不停地分解分解再分解
#include<stdio.h>
#define max(a,b) a>b?a:b
void yoouhuaa(int w[], int v[], int N[], int n, int &t)
{
int i,j;
for(i=0;i<n;i++){
for(j=1;j<=N[i];j*=2)
{
W[t]=w[i]*j;
V[t++]=v[i]*j;
N[i]-=j;
}
W[t]=w[i]*N[i];
V[t++]=v[i]*N[i];
}
}
int main()
{
int i,j,n,Q ,t=0;
int w[100],v[100],N[100],dp[10000],W[1000],V[1000]
scanf("%d%d",&n,&V);
for(i=0;i<n;i++)
scanf("%d%d%d",&w[i],&v[i],&N[i]);
yoouhua(w,v,N,n,t);
for(i=0;i<t;i++)
for(j=Q;j>=W[i];j--)
dp[j]=max(dp[j],dp[j-W[i]]+V[i]);
// dp[t] 即是最优的解;
}
OK;