[bzoj2287] [POJ Challenge] 消失之物

题目描述

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

img

输入输出格式

输入格式:

第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;
}
posted @ 2018-11-27 15:52  Hyscere  阅读(131)  评论(0编辑  收藏  举报