洛谷P4141消失之物(背包经典题)——Chemist
题目地址:https://www.luogu.org/problemnew/show/P4141
分析:这题当然可以直接暴力枚举去掉哪一个物品,然后每次暴力跑一遍背包,时间复杂度为O(m*n^2),显然超时。由于算去掉哪一个物品比较复杂,我们可以考虑容斥,算出他的补集,也就是选这个物品的方案数,然后用全集减去他的补集得到答案。算全集的过程就是跑一遍01背包,时间复杂度O(n^2),然后枚举去掉的物品i,再枚举背包的容积就j,算选择这个物品凑出这个容积的方案数就相当于算凑出j-w[i]的方案数,然后再强制选择一个i物品,用前面第一遍背包预处理求出的答案减去这个就是最终答案。然而我们还需要考虑一种情况,就是当前枚举的容积小于i物品的体积,也就是说在凑出j体积的背包时一直都没有选择i物品,也就不能去掉它,答案就是前面01背包预处理的值。
代码:
#include<bits/stdc++.h>
using namespace std;
const int M=2e3+10;
int n,m,w[M],f[M],g[M];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
f[0]=1;
//01背包:
for(int i=1;i<=n;i++)
for(int j=m;j>=w[i];j--)
f[j]=(f[j]+f[j-w[i]])%10;
for(int i=1;i<=n;i++)
{
memset(g,0,sizeof(g));
g[0]=1;
for(int j=1;j<=m;j++)
{
if(j>=w[i])g[j]=(f[j]-g[j-w[i]]+10)%10;
else g[j]=f[j];
printf("%d",g[j]);
}
puts("");
}
return 0;
}
独立意志与自由思想是必须争的,且须以生死力争。

浙公网安备 33010602011771号