• 洛谷 P1833 樱花


    洛谷 P1833 樱花

    原题链接

    Solution

    算法:多重背包

    但是裸的多重背包复杂度 (O(n*m*p))(p) 为物品个数),过不了此题,会 (TLE)

    我们考虑优化。

    多重背包有两种优化方法,一种是二进制拆分优化,另一种是单调队列优化

    这里只介绍一种:二进制拆分优化多重背包

    另一种以后有时间再补吧。

    顾名思义,我们要把数进行二进制拆分,那么我们要拆分什么呢?

    我们要把物品个数进行差分,例如有 19 个物品,我们要把它拆成 5个物品,每个物品个数分别为1, 2, 4,8,3。

    不难证明,这 5 个的任意组合可以表示出 1 ~ 19 的任意一个数,这也是二进制拆分优化的原理。

    我们把 19 拆成 5 个物品后,他们的价值和体积也要相应做出改变,即变为 个数 * 单个的价值/体积,跟总价 = 个数 * 单价一个原理。

    然后我们直接对拆分后的数组跑一个01背包即可,复杂度 (O(num * m))(num) 为拆分后的数组长度。

    完整代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int N = 10010;
    int h1, m1, h2, m2, n, m, num;
    int t[N], c[N], p[N], w[N * 15], v[N * 15], f[N];
    
    void prework(){			//二进制拆分,可以看着代码理解一下
    	for(int i = 1; i <= n; i++){
    		int tmp = 1;
    		while(p[i]){
    			w[++num] = tmp * t[i];
    			v[num] = tmp * c[i];
    			p[i] -= tmp;
    			tmp *= 2;
    			if(p[i] < tmp){
    				w[++num] = p[i] * t[i];
    				v[num] = p[i] * c[i];
    				break;
    			}
    		}
    	}
    }
    
    int main(){
    	scanf("%d:%d %d:%d %d", &h1, &m1, &h2, &m2, &n);
    	m = (60 * h2 + m2) - (60 * h1 + m1);
    	for(int i = 1; i <= n; i++){
    		scanf("%d%d%d", &t[i], &c[i], &p[i]);
    		if(!p[i]) p[i] = 1e4;			//赋成无穷大
    	}
    	prework();
    	for(int i = 1; i <= num; i++)		//注意这里是num
    		for(int j = m; j >= w[i]; j--)
    			f[j] = max(f[j], f[j - w[i]] + v[i]);
    	printf("%d
    ", f[m]);
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15115939.html

  • 相关阅读:
    leetcode 5286 网格中的最短路径
    C++ STL
    Transformer解读
    global_steps
    tensorflow中的一些语法问题
    生成器与yield关键字
    CNN神经网络一维卷积和二维卷积
    electron-builder打包后,运行的程序左上角图标不显示,桌面和状态栏的显示正常,是什么情况。
    git慢设置代理
    js使用正则表达式获取字符串中特定的字符
  • 原文地址:https://www.cnblogs.com/xixike/p/15115939.html
Copyright © 2020-2023  润新知