zoukankan      html  css  js  c++  java
  • 洛谷 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

  • 相关阅读:
    事务的特性(ACID)
    网络代理
    防止SpringMVC拦截器拦截js等静态资源文件
    Tomcat配置虚拟目录
    SpringMVC总结(SSM)
    Spring声明式事务总结
    Linux中MySQL忽略表中字段大小写
    MySQL之sql文件的导入导出
    MyBatis总结
    Linux网络
  • 原文地址:https://www.cnblogs.com/xixike/p/15115939.html
Copyright © 2011-2022 走看看