zoukankan      html  css  js  c++  java
  • [BZOJ2073][POI2004]PRZ

    [BZOJ2073][POI2004]PRZ

    试题描述

    一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的人都不能超过一定的限制. 所以这只队伍过桥时只能分批过,当一组全部过去时,下一组才能接着过. 队伍里每个人过桥都需要特定的时间,当一批队员过桥时时间应该算走得最慢的那一个,每个人也有特定的重量,我们想知道如何分批过桥能使总时间最少.

    输入

    第一行两个数: w – 桥能承受的最大重量(100 <= w <= 400) 和 n – 队员总数(1 <= n <= 16). 接下来n 行每行两个数分别表示: t – 该队员过桥所需时间(1 <= t <= 50) 和 w – 该队员的重量(10 <= w <= 100).

    输出

    输出一个数表示最少的过桥时间.

    输入示例

    100 3
    24 60
    10 40
    18 50

    输出示例

    42

    数据规模及约定

    见“输入

    题解

    设 f(S) 表示让 S 集合的人过桥所需要的最短总时间。转移的时候枚举子集即可。开始时预处理一下每个集合的重量总和与最大时间,这样状态数乘转移数就变成 3n 的了。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 20
    #define maxs 65536
    #define oo 2147483647
    
    int W, n, tim[maxn], wei[maxn], sumw[maxs], maxt[maxs], f[maxs];
    
    int dp(int S) {
    	if(f[S] < oo) return f[S];
    	if(sumw[S] <= W) return f[S] = maxt[S];
    	for(int tS = S - 1 & S; tS; tS = tS - 1 & S)
    		if(dp(tS) < oo && dp(S^tS) < oo) f[S] = min(f[S], dp(tS) + dp(S^tS));
    	return f[S];
    }
    
    int main() {
    	W = read(); n = read();
    	for(int i = 0; i < n; i++) tim[i] = read(), wei[i] = read();
    	
    	int all = (1 << n) - 1;
    	for(int S = 0; S <= all; S++)
    		for(int i = 0; i < n; i++) if(S >> i & 1)
    			maxt[S] = max(maxt[S], tim[i]), sumw[S] += wei[i];
    	for(int S = 0; S <= all; S++) f[S] = oo;
    	
    	printf("%d
    ", dp(all));
    	
    	return 0;
    }
    
  • 相关阅读:
    链表相交
    环路检测
    lambada表达式对集合的过滤和相互转换
    lambda表达式对集合的遍历
    centos7常用命令
    小程序文件
    扫码登录
    位操作
    使用json-lib转换对象为字符串时的特殊处理
    javac 编译异常总结
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6938568.html
Copyright © 2011-2022 走看看