zoukankan      html  css  js  c++  java
  • codeforces 1459D. Glass Half Spilled

    题面传送门


    首先这场比赛是真的爽,33分钟写完了三道题(虽然剩下的一个半点一道没搞出来),排名140多,涨了133rating.


    好了回归正题,这题确实挺难的(虽然tourist8分钟切掉了),因为他有两个思维阶段。


    我们记选的(k)个杯子的集合为(S),总容量为(A_S),含有的水为(B_S)。那么我们能得到最多的水是(min { A_S, B_S+frac{B-B_S}{2} })。因为分多次往一个杯子里倒水或者一个杯子往不同的杯子里倒水和一次性的把水都倒在一个杯子里是一样的(这个用小学数学就能证明)。
    那么现在的问题是如何选取集合(S),使(B_S)最大化。


    因为每一个杯子只有选和不选两种,因此可以用背包试一试:
    (a_i)看成体积,(b_i)看成价值,那么有(dp[i][A]),表示在前(i)个杯子中,总体积为(A)时得到的最大(B_S)。又因为题目要选刚好(k)个,所以我们就再加一维:(dp[i][k][A]),表示在前(i)个杯子中,选了(k)个,总容量为(A)时的最大(B_S)
    转移就呼之欲出了:(dp[i][k][A] = max {dp[i-1][k][A], dp[i-1][k-1][A-a_i]+b_i }).


    这就是题目数据范围为什么给了那么小的原因,而且还限制了(a_i)。时间复杂度(O(n^3A))((A=max {a_i })),空间复杂度需要仿照01背包将第一维优化掉,得到(O(n^3))


    没想到一道感觉相当复杂的题考的竟然是01背包,真的很喜欢这种知识本身不难但是需要大量思考的题。
    (话说题面要保证误差不超过(10^{-9})是什么鬼,果然是来坑向我这样的菜鸡的)

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<queue>
    #include<assert.h>
    #include<ctime>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 105;
    In ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), las = ' ';
    	while(!isdigit(ch)) las = ch, ch = getchar();
    	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    	if(las == '-') ans = -ans;
    	return ans;
    }
    In void write(ll x)
    {
    	if(x < 0) x = -x, putchar('-');
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    
    int n, a[maxn], b[maxn];
    int dp[maxn][maxn * maxn];
    
    int main()
    {
    	n = read();
    	int sa = 0, sb = 0;
    	for(int i = 1; i <= n; ++i)
    	{
    		a[i] = read(), b[i] = read();
    		sa += a[i], sb += b[i];
    	} 
    	Mem(dp, -1), dp[0][0] = 0;
    	for(int i = 1; i <= n; ++i)
    		for(int k = i; k; --k)
    			for(int A = sa; A >= a[i]; --A)
    				if(~dp[k - 1][A - a[i]]) dp[k][A] = max(dp[k][A], dp[k - 1][A - a[i]] + b[i]);
    	for(int i = 1; i <= n; ++i)
    	{
    		db tp = 0;
    		for(int j = 0; j <= sa; ++j) 
    			if(~dp[i][j]) tp = max(tp, min(1.0 * j, 0.5 * (sb + dp[i][j])));
    		printf("%.10lf ", tp);
    	}
    	enter;
    	return 0;
    }
    
  • 相关阅读:
    eVC4系列下载地址[更新](增加sp4)
    ABAP如何生成年月的输入帮助
    BW BW Connectivity(最佳实践适合BW3.5)
    MM公司委托加工流程
    ABAP一个读取EXCEL单元格的内容超过256个字符的代码样例
    ABAP如何实现合计字段分单位合计
    ABAPABAP程序员需要参加的课程
    ABAP关于ABAP Dictionary的一些简单问题
    FI分期收款发出商品物料数据(仅供参考)
    ABAP关于abap的subroutines的几个注意点
  • 原文地址:https://www.cnblogs.com/mrclr/p/14163934.html
Copyright © 2011-2022 走看看