[bzoj2287] [POJ Challenge] 消失之物
题目描述
ftiasch 有 N 个物品, 体积分别是 W1, W2, …, WN。 由于她的疏忽, 第 i 个物品丢失了。 “要使用剩下的 N – 1 物品装满容积为 x 的背包,有几种方法呢?” — 这是经典的问题了。她把答案记为 Count(i, x) ,想要得到所有1 <= i <= N, 1 <= x <= M的 Count(i, x) 表格。
输入输出格式
输入格式:
第1行:两个整数 N (1 ≤ N ≤ 2 × 10^3)N(1≤N≤2×103) 和 M (1 ≤ M ≤ 2 × 10^3)M(1≤M≤2×103),物品的数量和最大的容积。
第2行: N 个整数 W1, W2, …, WN, 物品的体积。
输出格式:
一个 N × M 的矩阵, Count(i, x)的末位数字。
输入输出样例
输入样例#1:
3 2
1 1 2
输出样例#1:
11
11
21
说明
如果物品3丢失的话,只有一种方法装满容量是2的背包,即选择物品1和物品2。
此为luogu题面,bzoj题面(权限题)
题解
简单背包题,每次逆循环消去一个物品的影响就行。
#include<bits/stdc++.h>
using namespace std;
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
void print(int x) {
if(x<0) x=-x,putchar('-');
if(!x) return ;print(x/10),putchar(x%10+'0');
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}
#define maxn 2000
int f[maxn+5],g[maxn+5],n,m,v[maxn+5];
int main() {
read(n),read(m);
for(int i=1;i<=n;i++) read(v[i]);
f[0]=1;
for(int i=1;i<=n;i++)
for(int j=m-v[i];j>=0;j--)
(f[j+v[i]]+=f[j])%=10;
for(int i=1;i<=n;i++) {
for(int j=0;j<=m;j++) g[j]=f[j];
for(int j=v[i];j<=m;j++) g[j]=((g[j]-g[j-v[i]])%10+10)%10;
for(int j=1;j<=m;j++) putchar(g[j]+'0');puts("");
}
return 0;
}