2287: 【POJ Challenge】消失之物

xiaoxiao2021-02-28  22

题目链接

题目大意:ftiasch 有 N 个物品, 体积分别是 W1, W2, …, WN。 由于她的疏忽, 第 i 个物品丢失了。 “要使用剩下的 N - 1 物品装满容积为 x 的背包,有几种方法呢?” – 这是经典的问题了。她把答案记为 Count(i, x) ,想要得到所有1 <= i <= N, 1 <= x <= M的 Count(i, x) 表格

题解: f[x] 表示恰好装满x体积的方案数,这个01背包一下

下面考虑不选物品i的情况 记g[x]为不选当前物品i恰好装满x体积的方案数

然后分类讨论一下 1. x<w[i] g[x]=f[x] 2. xw[i] 等于总方案数减去选到了i的方案数

那么该怎么得到选当前物品i恰好装满x体积的方案数呢?

可以把这个分成两步:

不选当前物品i恰好装满x-w[i]体积选当前物品i

即g[x]=f[x]-g[x-w[i]]

我的收获:特殊的姿势

#include<bits/stdc++.h> using namespace std; int n,m; int w[2010]; long long f[2010],g[2010]; void ZeroOne() { f[0]=1; for(int i=1;i<=n;i++) for(int j=m;j>=w[i];j--) f[j]=(f[j]+f[j-w[i]])%10; } void calc() { for(int i=1;i<=n;i++) { for(int j=0;j<w[i];j++) g[j]=f[j]; for(int j=w[i];j<=m;j++) g[j]=(f[j]-g[j-w[i]]+10)%10; for(int j=1;j<=m;j++) printf("%d",g[j]); putchar('\n'); } } void work() { ZeroOne(); calc(); } void init() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&w[i]); } int main() { init(); work(); return 0; }
转载请注明原文地址: https://www.6miu.com/read-2629423.html

最新回复(0)