zoukankan      html  css  js  c++  java
  • 消失之物「分治+背包」

    消失之物「分治+背包」

    题目描述

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

    输入格式

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

    (2) 行: (N) 个整数 (W_1, W_2, ..., W_N), 物品的体积。

    输出格式

    一个 (N × M) 的矩阵, (Count(i, x)) 的末位数字

    样例

    样例输入

    3 2
    1 1 2
    

    样例输出

    11
    11
    21
    

    思路分析

    • 直接暴力跑一个背包能拿70~80分(甚至完全可以用背包水过)
    • 不难发现,在每一次更新不能拿的物品时,其它可以拿的是有大量的重复计算的,所以考虑将其保留,直接使用
    • 这时候就可以用分治了,每次把一个区间分成两部分,一部分不动,另一部分去选不能拿的
    • 另外要注意,每一次更新答案之前要撤销对另一半答案的更新
    • 最后会分成一个长得像线段树的东西,每个相当于叶子结点的就代表该点不能拿,一共有 (log(n))

    详见代码

    (Code)

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define N 20200
    #define R register
    using namespace std;
    inline int read(){
    	int x = 0,f = 1;
    	char ch = getchar();
    	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	return x*f;
    }
    int n,m,a[N],f[20][N];
    void solve(int l,int r,int dep){ //dep表示当前分治树的深度
    	if(l==r){
    		for(R int i = 1;i <= m;i++)printf("%d",f[dep][i]);
    		puts("");
    		return;
    	}
    	int mid = (l+r)>>1;
    	for(R int i = m;i >= 0;i--)f[dep+1][i] = f[dep][i];
    	for(R int i = mid+1;i <= r;i++){ //右半部分全部都能拿,直接更新即可
    		for(R int j = m;j >= 0;j--){
    			f[dep+1][j] = (f[dep+1][j]+f[dep+1][j-a[i]])%10;
    		}
    	}
    	solve(l,mid,dep+1); //左半部分有不能拿的,递归解决
    	for(R int i = m;i >= 0;i--)f[dep+1][i] = f[dep][i]; //反过来再处理一下,在此之前要撤销
    	for(R int i = l;i <= mid;i++){
    		for(R int j = m;j >= 0;j--){
    			f[dep+1][j] = (f[dep+1][j]+f[dep+1][j-a[i]])%10;
    		}
    	}
    	solve(mid+1,r,dep+1);//同上
    }
    int main(){
    	n = read(),m = read();
    	for(R int i = 1;i <= n;i++)a[i] = read();
    	f[0][0] = 1;
    	solve(1,n,0);
    	return 0;
    }
    
  • 相关阅读:
    Tjoi 2017 异或和
    Noi 十连测 建造记者站
    Noi 十连测 基因改造计划
    Noi 十连测 人生的经验
    NOI 十连测 Round 5 T2 运河计划
    NOI 十连测 Round 5 T1
    【ZJOI2018】迷宫
    BZOJ 十连测 day5 T3
    BZOJ 十连测 可持久化字符串
    BZOJ 十连测 二进制的世界
  • 原文地址:https://www.cnblogs.com/hhhhalo/p/13616152.html
Copyright © 2011-2022 走看看