背包九讲地址:
file://C:\Users\PHC\AppData\Local\Packages\903DB504.QQ_a99ra4d2cbcxa\LocalState\User\1021861128\NetworkFile\背包问题九讲_2.0.pdf
完全背包的一种正常思路:
物品数量:
背包容量:
选择装多少个第i个物品:
完全背包的另一种思路:
改变01背包的第二个循环的顺序(逆序--->顺序)
非常的巧妙。
第一种写法的CODE(HDU1248):
#include <iostream>
#include <string>
#include <algorithm>
const int maxn = 1e5+10;
using namespace std;
int t,n,dp[maxn],tiji[4],jiazhi[4],rest;
int main()
{
cin>>t;
tiji[1]=150,tiji[2]=200,tiji[3]=350;
jiazhi[1]=150,jiazhi[2]=200,jiazhi[3]=350;
while(t--)
{
cin>>n;
rest=n;
for(int i=0;i<=n;++i) dp[i]=0;
for(int i=1;i<=3;++i)
for(int j=1;j<=n;++j)
for(int k=0;k*tiji[i]<=j;++k)
dp[j]=max(dp[j],dp[j-k*tiji[i]]+k*jiazhi[i]);
rest=n-dp[n];
cout<<rest<<endl;
}
}
第二种写法的CODE(也是1248):
#include <iostream>
#include <string>
#include <algorithm>
const int maxn = 1e5+10;
using namespace std;
int t,n,dp[maxn],tiji[4],jiazhi[4],rest;
int main()
{
cin>>t;
tiji[1]=150,tiji[2]=200,tiji[3]=350;
jiazhi[1]=150,jiazhi[2]=200,jiazhi[3]=350;
while(t--)
{
cin>>n;
rest=n;
for(int i=0;i<=n;++i) dp[i]=0;
for(int i=1;i<=3;++i)
for(int j=tiji[i];j<=n;++j)
dp[j]=max(dp[j],dp[j-tiji[i]]+jiazhi[i]);
rest=n-dp[n];
cout<<rest<<endl;
}
}
//伪代码1
for(int i=1;i<=n;++i)//放第i个物品
for(int j=1;j<=v;++j)//背包的体积
for(int k=0;k*weight[i]<=j;++k)//枚举放第i个物品的数量
dp[j]=max(dp[j],dp[j-k*weight[i]]+value[i]);//状态转移
//伪代码2
for(int i=1;i<=n;++i)//放第i个物品
for(int j=weight[i];j<=v;++j)//顺序枚举
dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);//状态转移