(上不了p站我要死了)

今天听了 doggu神 讲了这道题的另一种做法,真是脑洞大开、眼界大开。虽然复杂度比黄学长的要大一点,但不总结一下简直对不起这神思路。

方法1:黄学长的做法(点这里)

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。

这道题最开始会有两种想法:1、用总方案数减去用该物品的方案数,这个的分支的最终思路就是黄学长的做法。 2、去掉每一个物品,重新跑背包(这不是暴力吗喂?!)

假设我们没有想到 方法1,那该怎么办呢?我们可以很直观的感觉到:去掉i,我们要用1~i-1和i+1~n个物品去更新背包;去掉j,我们要用1~j-1和j+1~n个物品去更新背包。

其中大部分都是一样的,我们会直观的感觉到这是冗余部分,是不需要这么多次的,希望可以减少无用功。

首先,背包有个性质:物品更新的先后顺序并不影响最终结果,这是肯定的。

我们想:如果去掉 i、j,用剩余的n-2个物品去更新。再用 j 更新,就得到了去掉 i 的答案;同理,再用 i 去更新,就得到了 j 答案。对于多个物品的块,亦然。

那么我们是否就想到了分治?把物品分为上述的块,再来解决?

那么对于当前的分治状态solve(int le,int ri),此时我们已经用1~le-1和ri+1~n的物品将背包处理好了,直接处理该块没有意义,因为我们还可以将块分下去。将[le,ri]分为两段,如果要处理[le,mid],就用mid+1~ri的物品将之前更新好了的背包再更新一遍;同理,处理[mid+1,ri],就用le~mid的物品去更新之前的背包。

就这样递归下去,直到le==ri,这时的背包就是对于去掉le的答案了,输出即可。

因为是这是中序遍历,一共有log层,所以只需开log个背包即可

复杂度:因为每一层都要跑背包,共log层,所以总时间复杂度o(nmlogn),空间复杂度o(mlogn)

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int N=2000+5; int n,m,w[N];
int f[15][N]; void solve(int dep,int le,int ri){
if(le==ri){
for(int i=1;i<=m;i++) printf("%d",f[dep][i]%10);
printf("\n");
return;
}
int mid=(le+ri)>>1;
for(int j=0;j<=m;j++) f[dep+1][j]=f[dep][j];
for(int i=mid+1;i<=ri;i++)
for(int j=m;j>=w[i];j--)
f[dep+1][j]+=f[dep+1][j-w[i]],f[dep+1][j]%=10;//some items have been done
solve(dep+1,le,mid);
for(int j=0;j<=m;j++) f[dep+1][j]=f[dep][j];
for(int i=le;i<=mid;i++)
for(int j=m;j>=w[i];j--)
f[dep+1][j]+=f[dep+1][j-w[i]],f[dep+1][j]%=10;
solve(dep+1,mid+1,ri);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
f[0][0]=1;
solve(0,1,n);
return 0;
}

就算不是最优的,但这思路实在是巧。提高自己的眼界总归是一件好事。

旧题再做【bzoj2287】【[pojchallenge]消失之物】分治背包的更多相关文章

  1. 【BZOJ2287】消失之物 [分治][DP]

    消失之物 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ftiasch 有 N 个物品, ...

  2. [bzoj2287][poj Challenge]消失之物_背包dp_容斥原理

    消失之物 bzoj-2287 Poj Challenge 题目大意:给定$n$个物品,第$i$个物品的权值为$W_i$.记$Count(x,i)$为第$i$个物品不允许使用的情况下拿到重量为$x$的方 ...

  3. [bzoj2287]消失之物 题解(背包dp)

    2287: [POJ Challenge]消失之物 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1138  Solved: 654[Submit][ ...

  4. bzoj2287【POJ Challenge】消失之物(退背包)

    2287: [POJ Challenge]消失之物 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 657  Solved: 382[Submit][S ...

  5. 旧题新做:从idy的视角看数据结构

    “今天你不写总结……!!!” 额…… 还是讲我的吧.这些考试都是idy出的题. 20170121:DFS序. ST表.线段树练习 这是第一次考数据结构. Problem 1. setsum 1 sec ...

  6. 洛谷P4141消失之物(背包经典题)——Chemist

    题目地址:https://www.luogu.org/problemnew/show/P4141 分析:这题当然可以直接暴力枚举去掉哪一个物品,然后每次暴力跑一遍背包,时间复杂度为O(m*n^2),显 ...

  7. 2018.11.06 bzoj2287: 【POJ Challenge】消失之物(背包)

    传送门 先假设所有物品都能用,做01背包求出方案数. 然后枚举每个点,分类讨论扣掉它对答案的贡献. 代码: #include<bits/stdc++.h> using namespace ...

  8. luogu p4141 消失之物(背包dp+容斥原理)

    题目传送门 昨天晚上学长讲了这题,说是什么线段树分治,然后觉得不可做,但那还不是正解,然后感觉好像好难的样子. 由于什么鬼畜的分治不会好打,然后想了一下$O(nm)$的做法,想了好长时间觉得这题好像很 ...

  9. BZOJ.2287.[POJ Challenge]消失之物(退背包)

    BZOJ 洛谷 退背包.和原DP的递推一样,再减去一次递推就行了. f[i][j] = f[i-1][j-w[i]] + f[i-1][j] f[i-1][j] = f[i][j] - f[i-1][ ...

随机推荐

  1. tensorflow2.0 numpy.ndarray 与tenor直接互转

    1.代码参考 import numpy as npimport tensorflow as tf a = np.random.random((5,3)) b = np.random.randint(0 ...

  2. TortoiseSVN-1.9.7 对应 eclipse svn 插件的 更新

    用TortoiseSVN在文件夹导入项目之后,用eclipse 导入发现没有SVN信息,无法同步工程.出现这个情况先不管 TortoiseSVN的版本,直接把eclipse的svn版本升级到最新. H ...

  3. 【C语言--数据结构】线性顺序表

    线性表的本质: 1.线性表(List)是零个或者多个数据元素的集合: 2.线性表中的数据元素之间是有顺序的: 3.线性表中的数据元素个数是有限的: 4.线性表中的数据元素的类型必须相同: 定义: 线性 ...

  4. Linux环境安装mongodb

    介绍 上篇介绍了Linux环境下安装Node.js的步骤,紧接着来安装mongodb.另外,推荐我的另一篇 Windows下图文详解Mongodb安装及配置,先在Windows下熟悉下mongodb, ...

  5. The order of a Tree

    The order of a Tree Problem Description As we know,the shape of a binary search tree is greatly rela ...

  6. 【模板】最长上升子序列(LIS)及其优化 & 洛谷 AT2827 LIS

    最长上升子序列 传送门 题意 对于给定的一个n个数的序列,找到它的一个最长的子序列,并且保证这个子序列是由低到高排序的. 例如,1 6 2 5 4 6 8的最长上升子序列为1 2 4 6 8. 基本思 ...

  7. 小白学Python——用 百度AI 实现 OCR 文字识别

    百度AI功能还是很强大的,百度AI开放平台真的是测试接口的天堂,免费接口很多,当然有量的限制,但个人使用是完全够用的,什么人脸识别.MQTT服务器.语音识别等等,应有尽有. 看看OCR识别免费的量 快 ...

  8. /cat/cpuinfo信息查看

    # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数cat /proc/cpuinfo| g ...

  9. django2.0变动数据库设置外键报错

    1.报错TypeError: __init__() missing 1 required positional argument: 'on_delete' django2.0以后创建数据库外键的时候必 ...

  10. RNN, LSTM, GRU cells

    项目需要,先简记cell,有时间再写具体改进原因 RNN cell LSTM cell: GRU cell: reference: 1.https://towardsdatascience.com/a ...