「
「
「动态规划
」
」
」第
1
1
1章 背包问题
(
(
(后
2
2
2题
)
)
)
目录:
D.硬币方案
E.金明的预算方案
D . D. D. 例题 4 4 4 硬币方案
分析:
若
f
i
f_i
fi为
1
1
1表示面值为
i
i
i的硬币可以凑成
c
n
t
i
cnt_i
cnti表示离
i
i
i最近一个
f
i
=
1
f_i=1
fi=1的距离 如果小于
c
i
c_i
ci 就可以更新
c
n
t
i
cnt_i
cnti
这样也统计了用了的硬币数量 就可以优化了
CODE:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<bitset>
//#pragma GCC optimize(2)
#define reg register
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int N=105,M=1e5+5;
int a[N],c[N],f[M],cnt[M],n,S,ans;
int main()
{
scanf("%d%d",&n,&S);
while(n&&S)
{
ans=0;
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
f[0]=1;
for(int i=1;i<=n;i++)
{
memset(cnt,0,sizeof(cnt));
for(int j=a[i];j<=S;j++)
if(!f[j]&&f[j-a[i]]&&cnt[j-a[i]]<c[i])
{
f[j]=1;
cnt[j]=cnt[j-a[i]]+1;
}
}
for(int i=1;i<=S;i++)
if(f[i]) ans++;
printf("%d\n",ans);
scanf("%d%d",&n,&S);
}
return 0;
}
E . E. E. 例题 5 5 5 金明的预算方案
分析:
先处理出主件和附件的价值和重量
然后就是
01
01
01背包了
1.
1.
1.只买主件
2.
2.
2.买主件
+
+
+附件
1
1
1
3.
3.
3.买主件
+
+
+附件
2
2
2
4.
4.
4.买主件
+
+
+附件1
+
+
+附件
2
2
2
分别判断下就行了
CODE:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<bitset>
//#pragma GCC optimize(2)
#define reg register
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int N=3e4+2e3+5;
int n,m,w[N],v[N],add_w[N][3],add_v[N][3],c,p,q,f[N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&c,&p,&q);
if(q==0) //主件
{
w[i]=c;
v[i]=c*p;
}
else //附件
{
add_w[q][0]++;
int k=add_w[q][0];
add_w[q][k]=c;
add_v[q][k]=c*p;
}
}
for(int i=1;i<=m;i++)
for(int j=n;j>=w[i];j--)
{
f[j]=max(f[j],f[j-w[i]]+v[i]);
if(j>=w[i]+add_w[i][1]) f[j]=max(f[j],f[j-w[i]-add_w[i][1]]+v[i]+add_v[i][1]);
if(j>=w[i]+add_w[i][2]) f[j]=max(f[j],f[j-w[i]-add_w[i][2]]+v[i]+add_v[i][2]);
if(j>=w[i]+add_w[i][1]+add_w[i][2])
f[j]=max(f[j],f[j-w[i]-add_w[i][1]-add_w[i][2]]+v[i]+add_v[i][1]+add_v[i][2]);
}
printf("%d",f[n]);
return 0;
}