做了两道背包问题,迷迷糊糊也算是弄懂了一些背包的模型。
poj1837
这个题主要是建立背包模型bi比较难,当时没有想到第二维可以是平衡状态,看到网上大佬的提示才想到,代码如下
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int dp[25][15005],d[25],w[25],n,m,x,y,z,k,l;
int main(){
cin>>n>>m;
for (int i=1; i<=n; i++) cin>>d[i];
for (int i=1; i<=m; i++) cin>>w[i];
memset(dp,0,sizeof(dp));
dp[0][7500]=1;
for (int i=1; i<=m; i++)
for (int j=1; j<=15000; j++)
if (dp[i-1][j]){
for (int k=1; k<=n; k++) dp[i][j-w[i]*d[k]]+=dp[i-1][j];
}
cout<<dp[m][7500]<<endl;
return 0;
}
poj1726
这道题我一开始是懵比的,上网学习了多重背包之后也是懵比的,最后把01,完全,多重都看了一边才有了头绪,我自己写的用了二进制拆分(听起来很难写起来简单),网上大佬有用num数组做的我还没看懂,先存下来慢慢研究
这是我的
//完全背包
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int dp[100005],cash[2000][2],cnt[100000],n,m,x,y,z,k,l,w;
int main(){
while (cin>>w){
memset(dp,0,sizeof(dp));
memset(cash,0,sizeof(cash));
memset(cnt,0,sizeof(cnt));
cin>>n;
for (int i=1; i<=n; i++){
cin>>cash[i][0]>>cash[i][1];
}
int t=0;
for (int i=1; i<=n; i++){
if (cash[i][0]==0 || cash[i][1]==0) continue;
k=1;
while (cash[i][0]>k){
t++;
cnt[t]=k*cash[i][1];
cash[i][0]-=k;
k*=2;
}
if (cash[i][0]>0 && cash[i][1]>0){
t++;
cnt[t]=cash[i][0]*cash[i][1];
}
}
for (int i=1; i<=t; i++)
for (int j=w; j>=cnt[i]; j--){
dp[j]=max(dp[j],dp[j-cnt[i]]+cnt[i]);
}
cout<<dp[w]<<endl;
}
return 0;
}
大佬的
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[110000],num[100100],s[2000][2];
int main()
{
int cash,n;
while(scanf("%d%d",&cash,&n)>0)
{
int cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&s[i][0],&s[i][1]);
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
memset(num,0,sizeof(num));
for(int j=s[i][1];j<=cash;j++)
if(dp[j]<dp[j-s[i][1]]+s[i][1]&&num[j-s[i][1]]<s[i][0])
{
dp[j]=dp[j-s[i][1]]+s[i][1];
num[j]=num[j-s[i][1]]+1;
}
}
printf("%d\n",dp[cash]);
}
return 0;
}
还有多重背包的模板
for(int i=1;i<=n;i++)
{
memset(num,0,sizeof(num));
for(int j=v[i];j<=maxn;j++)
{
if(dp[j-v[i]&&!dp[j]&&num[j-v[i]]<w[i])
{
....... //具体操作因题而异
num[j]=num[j-v[i]]+1; //求num[j]对应的使用数
}
}
}