bzoj2287 【POJ Challenge】消失之物

http://www.elijahqi.win/2018/01/15/bzoj2287-%e3%80%90poj-challenge%e3%80%91%e6%b6%88%e5%a4%b1%e4%b9%8b%e7%89%a9/
Description

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

Input

第1行:两个整数 N (1 ≤ N ≤ 2 × 103) 和 M (1 ≤ M ≤ 2 × 103),物品的数量和最大的容积。

第2行: N 个整数 W1, W2, …, WN, 物品的体积。
Output

一个 N × M 的矩阵, Count(i, x)的末位数字。
Sample Input
3 2
1 1 2
Sample Output
11
11
21
HINT

如果物品3丢失的话,只有一种方法装满容量是2的背包,即选择物品1和物品2。
首先n个物品每个物品体积分别是w1 w2 w3求这个体积 一共多少种方案数可以购买 那么这是一个经典问题 那么题目要求我们输出不用某种物品 然后填满容积为x的方案数
怎么办 首先按照01背包 我求出没有哪件物品不被选的方案数
接下来 我针对每种物品 设cnt[i]表示填满i容积的背包我不需要 j号物品的方案数 那么对于cnt[i]=dp[i]-cnt[i-v[j]] 我的值就是总的方案数-i-v[j]不需要j号位置填的方案数 那么就相当于减去了需要v[i]物品填满的方案

#include<cstdio>
#include<cstring>
#define N 2200
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0;char ch=gc();
    while(ch<'0'||ch>'9') ch=gc();
    while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
    return x;
}
int dp[N],n,m,cnt[N],a[N];
int main(){
    //freopen("bzoj2287.in","r",stdin);
    n=read();m=read();
    for (int i=1;i<=n;++i)a[i]=read();dp[0]=1;
    for (int i=1;i<=n;++i) for (int j=m;j>=a[i];--j) dp[j]+=dp[j-a[i]],dp[j]%=10;
    for (int i=1;i<=n;++i){
        memset(cnt,0,sizeof(cnt));cnt[0]=1;
        for (int j=1;j<=m;++j){
            if (j<a[i]) cnt[j]=dp[j];
            else{
                cnt[j]=dp[j]-cnt[j-a[i]];cnt[j]+=10;cnt[j]%=10;
            }
        }
        for (int j=1;j<=m;++j) printf("%d",cnt[j]);puts("");
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值