• [bzoj1775][Usaco2009 Dec]Vidgame 电视游戏问题_背包dp


    1775: [Usaco2009 Dec]Vidgame 电视游戏问题

    目链接https://www.lydsy.com/JudgeOnline/problem.php?id=1775


    题解

    发现是个$zz$分组背包。

    但是,正常的分组背包是,完全背包+01背包,在这里根本行不通因为数据范围。

    故此我们考虑背包$dp$。

    状态:$f_{(i,j)}$表示前$i$组,$i$选,花费$j$的最大价值;$g_{(i,j)}$表示$i$不选。

    因为空间开的下,所以我们可以把$i$也放进去。

    不然$i$是可以滚掉的。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int f[51][100001], g[51][100001];
    
    char *p1, *p2, buf[100000];
    
    #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
    
    int rd() {
    	int x = 0;
    	char c = nc();
    	while (c < 48) {
    		c = nc();
    	}
    	while (c > 47) {
    		x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
    	}
    	return x;
    }
    
    int main() {
        int n, m;
    	n = rd(), m = rd();
        memset(f, 0x80, sizeof f);
        memset(g, 0x80, sizeof g);
    	for (int i = 0; i <= m; i ++ ) {
            f[0][i] = g[0][i] = 0;
    	}
    	for (int i = 1; i <= n; i ++ ) {
    		int p = rd(), c = rd();
    		for (int j = 0; j <= m; j ++ ) {
                f[i][j] = max(f[i - 1][j], g[i - 1][j]);
                if (j >= p) {
                    g[i][j] = max(f[i - 1][j - p], g[i - 1][j - p]);
    			}
            }
            while (c -- ) {
    			int v = rd(), w = rd();
    			for (int j = m; j >= v; j -- ) {
                    g[i][j] = max(g[i][j], g[i][j - v] + w);
    			}
            }
        }
    	cout << max(f[n][m], g[n][m]) << endl ;
        return 0;
    }
    

    小结:如果常规地维护一个答案数组并不好维护,我们可以考虑把每个时刻的数组都维护出来。

  • 相关阅读:
    函数特化
    模板函数总结
    学习代码1
    宏指令
    #define宏作用
    oracle 重要函数
    JMeter 系列之—-01 使用
    Selenium系列之--03 常见元素操作总结
    【转】TestNG常用注解
    CMMI 2,3,4,5级涉及的过程域(PA)介绍
  • 原文地址:https://www.cnblogs.com/ShuraK/p/11420702.html
Copyright © 2020-2023  润新知