完全背包问题
完全背包每件物品可选取的次数是没有上限的。这是用闫氏分析法完全背包的基本思路:
显然完全背包f[i,j]的状态和f[i,j-v]有关,优化一维内存需要从小到大枚举体积。
#include<bits/stdc++.h>
using namespace std;
const int N=1001;
int v[N],w[N],f[N];
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;++i)
cin>>v[i]>>w[i];
for(int i=1;i<=n;++i){
for(int j=v[i];j<=m;++j){
f[j]=max(f[j],f[j-v[i]]+w[i]);
}
}
cout<<f[m]<<endl;
return 0;
}
900. 整数划分
思路:
将n个数字当作n个价值为i的物品,n也是背包体积。
#include<bits/stdc++.h>
using namespace std;
const int N=1010,mod=1e9+7;
int f[N];
int main(){
int n;
cin>>n;
f[0]=1;
for(int i=1;i<=n;++i){
for(int j=i;j<=n;++j){
f[j]+=f[j-i];
f[j]%=mod;
}
}
cout<<f[n]<<endl;
return 0;
}
532. 货币系统
思路: 当一张币值能通过其他方法组合得到,说明此币值是不必要的。
#include<iostream>
#include<string.h>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#include<set>
#include<map>
using namespace std;
const int N=30000;
int f[N],w[110];
int main(){
int n;
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(f,0,sizeof f);
f[0]=1;
for(int i=0;i<n;++i){
scanf("%d",&w[i]);
for(int j=w[i];j<N;++j){
f[j]+=f[j-w[i]];
}
}
int cnt=0;
for(int i=0;i<n;++i){
if(f[w[i]]>1) cnt++;
}
cout<<n-cnt<<endl;
}
return 0;
}