1. 程式人生 > >[bzoj2287] 【POJ Challenge】消失之物

[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;
}