1.[NOIP2018]货币系统
思路:完全背包问题求方案数 如果排完序以后 某一个数不能被前面的数表达出来 那么这个数肯定是不能被后面的数表示的 那么这个数肯定是要假如货币系统里面的
#include <bits/stdc++.h>
using namespace std;
const int N=110;
int a[N];
int f[25010];
void solve()
{
int n;cin>>n;
memset(f,0,sizeof f);
f[0]=1;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
int maxl=a[n];
int cnt=0;
for(int i=1;i<=n;i++)
{
int v=a[i];
if(!f[v]) cnt++;
for(int j=v;j<=maxl;j++)
{
f[j]+=f[j-v];
}
}
cout<<cnt<<endl;
return ;
}
int main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
}
2.多重背包
板子
#include<bits/stdc++.h>
using namespace std;
const int M=40010;
int n,m;
int v[1100],w[1100];
int f[M];
int main()
{
cin>>n>>m;
int cnt=0;
for(int i=1;i<=n;i++)
{
int a,b,s;
cin>>s>>a>>b;
int k=1;
while(k<=s)
{
cnt++;
v[cnt]=a*k;
w[cnt]=b*k;
s-=k;
k*=2;
}
if(s>0)
{
cnt++;
v[cnt]=a*s;
w[cnt]=b*s;
}
}
n=cnt;
for(int i=1;i<=n;i++)
for(int j=m;j>=v[i];j--)
f[j]=max(f[j],f[j-v[i]]+w[i]);
cout<<f[m]<<endl;
return 0;
}
3.金明的预算方案
思路:把主件和附件看成一组 然后有四种选法选主 附1 附2或 主 或 主 附1或 主 附2 这四种组合看成一个组 就可以当成分组背包问题了
#include <bits/stdc++.h>
#define v first
#define w second
using namespace std;
typedef pair<int,int>PII;
const int N=60,M=32010;
int n,m;
PII master[N];
vector<PII> servent[N];
int f[M];
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
{
int v,p,q;
cin>>v>>p>>q;
p*=v;
if(!q) master[i]={v,p};
else servent[q].push_back({v,p});
}
for(int i=1;i<=n;i++)
if(master[i].v)
for(int j=m;j>=0;j--)
{
for(int k=0;k<1<<(servent[i].size());k++)
{
int v=master[i].v,w=master[i].w;
for(int u=0;u<servent[i].size();u++)
{
if(k>>u&1)
{
v+=servent[i][u].v;
w+=servent[i][u].w;
}
}
if(j>=v) f[j]=max(f[j],f[j-v]+w);
}
}
cout<<f[m]<<endl;
return 0;
}