首页 > 其他分享 >[luogu p2160] [SHOI2007]书柜的尺寸

[luogu p2160] [SHOI2007]书柜的尺寸

时间:2022-09-28 20:14:13浏览次数:88  
标签:本书 ch int luogu p2160 第一层 高度 宽度 SHOI2007

[P2160 SHOI2007]书柜的尺寸 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

把书按高度从大到小排序,依次考虑放置,每一层第一个被放置的书的高度就是这一层的高度。

设 \(f(i, j, k, l)\) 表示考虑了前 \(i\) 本书,第一层宽度为 \(j\),第二层宽度为 \(k\),第三层宽度为 \(l\) 时,最小的整个书架的高度。(紫题应该就在于这个状态比较难想)

为什么会这么想,首先考虑 \(t_i\) 和 \(h_i\) 范围很小,可以猜测是 dp 的某一维,而且发现不这么设也很难转移;

其次,如果考虑前 \(i\) 本书,第一层高度为 \(j\),第二层高度为 \(k\),第三层高度为 \(l\) 的最小化整个书架的宽度,会发现很难转移,因为根本没有利用好开头所说的那个结论。

想到更换转移,于是有了上面的状态设计,发现这样就容易转移了。

刷表转移,对于 \(p = f(i, j, k, l)\),我们考虑对第一层进行放书,第二第三层完全同理。

下一个状态是 \(f(i + 1, j + t_i, k, l)\)。如果 \(j = 0\),把它和 \(p + h_i\) 取一个最小值,代表放了第一层放下了第一本书,我们统计上第一层的高度;否则如果 \(j \ne 0\),代表第一层已经放过一本书了,直接把它和 \(p\) 取一个最小值——显然第一层的高度已经统计在里面了。

发现时空复杂度仍然危险,考虑优化。

其实很容易发现 \(i, j, k\) 确定了 \(l\) 也就确定了,具体来说前 \(i\) 本书都放在书架中,第三层的宽度就是前 \(i\) 本书的总宽度减去第一层的宽度 \(j\) 减去第二层的宽度 \(k\)。因此第四维可以删掉。

然后这个题第一维还需要一个滚动。

统计答案就是直接大力统计最后状态。

时间复杂度 \(\mathcal{O}(n^3t^2)\),\(t\) 表示 \(t_i\) 的数量级。

这个题是 SHOI 2007,可以看到这题当时时限开了 5s,但是现在 1s 就可过,时代的进步~

/*
 * @Author: crab-in-the-northeast 
 * @Date: 2022-09-23 21:02:08 
 * @Last Modified by: crab-in-the-northeast
 * @Last Modified time: 2022-09-23 22:35:56
 */
#include <bits/stdc++.h>

inline int read() {
	int x = 0;
	bool flag = true;
	char ch = getchar();
	while (!isdigit(ch)) {
		if (ch == '-')
			flag = false;
		ch = getchar();
	}
	while (isdigit(ch)) {
		x = (x << 1) + (x << 3) + ch - '0';
		ch = getchar();
	}
	if(flag)
		return x;
	return ~(x - 1);
}

const int maxn = 75;
const int maxm = maxn * 35;

int f[2][maxm][maxm];

struct node {
	int h, t;
}a[maxn];

inline bool getmin(int &a, int b) {
	return b < a ? a = b, true : false;
}

inline bool getmin(long long &a, long long b) {
	return b < a ? a = b, true : false;
}

int main() {
	int n = read(); 
	for (int i = 1; i <= n; ++i) {
		int h = read(), t = read();
		a[i] = (node){h, t};
	}

	std :: sort(a + 1, a + 1 + n, [](node b, node c) {
		return b.h > c.h;
	});
	
	std :: memset(f[0], 0x3f, sizeof(f[0]));
	f[0][0][0] = 0;

	int x = 0;
	for (int u = 1; u <= n; x += a[u].t, ++u) {
		int i = u & 1, t = a[u].t, h = a[u].h;
		std :: memset(f[i], 0x3f, sizeof(f[i]));
		for (int j = 0; j <= x; ++j) {
			for (int k = 0; k <= x - j; ++k) {
				int p = f[i ^ 1][j][k];
				getmin(f[i][j + t][k], p + (j ? 0 : h));
				getmin(f[i][j][k + t], p + (k ? 0 : h));
				int l = x - j - k;
				getmin(f[i][j][k], p + (l ? 0 : h));
			}
		}
	}

	long long ans = LONG_LONG_MAX;
	for (int i = 1; i < x; ++i)
		for (int j = 1; j < x - i; ++j)
			getmin(ans, 1LL * std :: max({i, j, x - i - j}) * f[n & 1][i][j]);
	
	printf("%lld\n", ans);
	return 0;
}

标签:本书,ch,int,luogu,p2160,第一层,高度,宽度,SHOI2007
From: https://www.cnblogs.com/crab-in-the-northeast/p/luogu-p2160.html

相关文章

  • Luogu2607 & Luogu1453 基环树dp
    2607:一个基环树,有点权,全是有向边,选儿子则不能选父亲(反之亦然),问选出的集合的最大点权和注意到题目的特殊性,如果i->hatred[i],那么就是一个内向树,否则为外向树内向树好找环,......
  • luogu P4677 山区建小学
    山区建小学题目描述政府在某山区修建了一条道路,恰好穿越总共\(n\)个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往。已知任意两个相邻的村庄之间的距......
  • luogu P1043 [NOIP2003 普及组] 数字游戏
    [NOIP2003普及组]数字游戏题目描述丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容......
  • luogu P1385 密令
    密令题目描述给定一小写字母串\(s\),每次操作你可以选择一个\(p\)(\(1\leqp\lt|s|\))执行下述修改中的任意一个:将\(s_p\)改为其字典序\(+1\)的字母,将\(s_{p+1}......
  • 【luogu P6419】Kamp(换根DP)
    Kamp题目链接:luoguP6419题目大意一棵树上有一些点有人,边有通过的长度,然后对于每个点,你从这个点出发经过所有人(不用回到原来位置)的最短时间。其它人不会动,只有你去找人......
  • [luogu3980]志愿者招募
    记$x_{i}$为第$i$类志愿者数量$,y_{j}=\sum_{j\in[s_{i},t_{i}]}x_{i}-a_{j}$​,则问题即$$\foralli\in[1,m],x_{i}\ge0\\\forallj\in[1,n],y_{j}\ge0\\y_{1}-\sum_{......
  • 【luogu CF1109E】Sasha and a Very Easy Test(线段树)
    SashaandaVeryEasyTest题目链接:luoguCF1109E题目大意维护一个长度为n的序列,有区间乘,单点除(保证能整除),区间求和答案对p取模。p不一定是质数。思路麻了考场......
  • [luogu p8251] [NOI Online 2022 提高组] 丹钓战
    [P8251NOIOnline2022提高组]丹钓战-洛谷|计算机科学教育新生态(luogu.com.cn)容易发现对于一次查询\([L,R]\),\(L\)一定是第一个入栈的,也是成功的,答案至少为......
  • luogu P1052 [NOIP2005 提高组] 过河
    [NOIP2005提高组]过河题目描述在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳......
  • luogu P2233 [HNOI2002]公交车路线
    [HNOI2002]公交车路线题目描述在长沙城新建的环城公路上一共有\(8\)个公交站,分别为A、B、C、D、E、F、G、H。公共汽车只能够在相邻的两个公交站之间运行,因此你从某一......