flower 解题报告
前言
今天照常,七点四十五分开始打模拟赛,十一点四十五分时结束……

题目描述
hzwer 有 \(n\) 种花。
一开始,hzwer 只有这些花的种子,每一天,hzwer 可以种植一种当前未开放的花,或者给一种已开放的花施肥。
第 \(i\) 种花有一个描述其培育难易程度的 \(m_i\) 值,当种下第 \(i\) 种新的花后,它能够从种植之日起开放 \(m_i\) 天(含当天),之后便会枯萎。比如,若一种花的 \(m_i\) 值为 \(2\),则种植之后,若不继续施肥,则它只在种植的当日和次日开放。
当给第 \(i\) 种植物施肥之后,这种花开放的时间能够额外延长 \(m_i\) 天。
hzwer 想给他的妹子办个花展(可以在进行种植/施肥之后的当天办),显然花展上这 \(n\) 种花都得开放,现在 hzwer 想知道他最早要在第几天才能给妹子办花展,如果他无论如何都办不了花展,那么就输出 Poor hzwer!。
分析
首先,对于绝大部分情况都是一定有解的,只要把每一种花都反复施肥足够多次,就可以让它们支撑到花展。那么,什么情况无解呢?只当存在这样一种情况:一种花不管施多少次肥都无法支撑到另一朵开,也就是说存在两种以上花的 \(m_i=1\)。
可以看到,这道题似乎用贪心不太好解决,原因是不同的花的枯萎时间难以计算,即状态很多。这让我们想到动态规划。考虑什么因素会影响某种状态下的答案:每盆花的枯萎时间都可能会影响到。注意到这道题 \(n \le 20\),所以可以用状态压缩,也就是用一个二进制数表示每盆花是否被种植。
设 \(f[i]\) 表示已经种植的状态为 \(i\) 的情况下,最少还需要多少天才能开花展。考虑刷表法:从已经种植的状态中去除一种,答案就是当前答案加上被去除的花所需要的天数(\(\lceil\frac{f[i]}{m_i-1}\rceil\))。
至此,这个问题已经被解决。最后注意多测要清空。
题解
#include <bits/stdc++.h>
using namespace std;
#define int long long
int dp[(1 << 18) + 10];
int n, m[20];
signed main() {
int _;
cin >> _;
while (_--) {
cin >> n;
memset(dp, 0x3f, sizeof(dp));
int cnt1 = 0;
for (int i = 0; i < n; i++) {
cin >> m[i];
if (m[i] == 1) {
cnt1++;
dp[(1 << n) - (1 << i) - 1] = 1;
}
}
if (cnt1 > 1) {
cout << "Poor hzwer!\n";
continue;
}
// for (int i = 0; i < n; i++) dp[1 << i] = 1;
dp[(1 << n) - 1] = 0;
for (int i = (1 << n) - 1; i >= 0; i--) {
for (int j = 0; j < n; j++) {
if (i & (1 << j)) {
if (m[j] != 1) {
dp[i ^ (1 << j)] = min(dp[i ^ (1 << j)], dp[i] + max(1ll, (dp[i] - 1) / (m[j] - 1) + 1));
}
}
}
}
cout << dp[0] << '\n';
}
return 0;
}
结语
……挂了很多分,和正解没挨上一点边,算是非常坏了!
本文来自博客园,作者:cwkapn,转载请注明原文链接:https://www.cnblogs.com/cwkapn/p/18909487


浙公网安备 33010602011771号