zoukankan      html  css  js  c++  java
  • [HDOJ 1171] Big Event in HDU 【完全背包】

    题目链接:HDOJ - 1171

    题目大意

    有 n 种物品,每种物品有一个大小和数量。要求将所有的物品分成两部分,使两部分的总大小尽量接近。

    题目分析

    令 Sum 为所有物品的大小总和。那么就是用给定的物品做完全背包,背包容量为 (Sum / 2) ,得到的结果是较小的一部分的大小。

    完全背包问题可以使用单调队列优化,O(nm) 。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    const int MaxN = 1000 + 5, MaxM = 250000 + 5;
    
    int n, Sum, Sum1, A, B, Head1, Tail1, Head2, Tail2;
    int V[MaxN], Num[MaxN], Q1[MaxM], Q2[MaxM], f[MaxM];
    
    int main() 
    {
    	while (true) {
    		scanf("%d", &n);
    		if (n < 0) break;
    		Sum = 0;
    		for (int i = 1; i <= n; ++i) {
    			scanf("%d%d", &V[i], &Num[i]);
    			Sum += V[i] * Num[i];
    		}
    		Sum1 = Sum >> 1;
    		for (int i = 0; i <= Sum1; ++i) f[i] = 0;
    		int Ni, Vi, t;
    		for (int i = 1; i <= n; ++i) {
    			Ni = Num[i]; Vi = V[i];
    			for (int j = 0; j < Vi; ++j) {
    				Head1 = Tail1 = 0;
    				Head2 = Tail2 = 0;
    				for (int k = j, Cnt = 0; k <= Sum1; k += Vi, ++Cnt) {
    					if (Tail1 - Head1 == Ni + 1) {
    						if (Q2[Head2 + 1] == Q1[Head1 + 1]) ++Head2;
    						++Head1;
    					}
    					t = f[k] - Cnt * Vi;
    					Q1[++Tail1] = t;
    					while (Head2 < Tail2 && Q2[Tail2] < t) --Tail2;
    					Q2[++Tail2] = t;
    					f[k] = Q2[Head2 + 1] + Cnt * Vi;
    				}
    			}
    		}
    		B = f[Sum1];
    		A = Sum - B;
    		printf("%d %d
    ", A, B);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Seaborn学习笔记2
    Seaborn学习笔记1
    HTML学习笔记4
    HTML学习笔记3
    HTML学习笔记2

    指针与引用
    函数
    字符串
    C++简易
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4168024.html
Copyright © 2011-2022 走看看