[CF1579G] Minimal Coverage
怎么这个题想不到啊,所以我选择了看题解。
不容易发现,如果覆盖长度为 \(x\) 可以,那长度更多的一定可以(这里不盖满整个长度为 \(x\) 的段也可以)。
二分试一试,令当前二分的覆盖长度为 \(len\)。
DP 一下,\(f_{i, j}\) 表示放完 \(1 \sim i\) 的线段,结尾能否位置 \(j\)。
\(f_{i, j}\) 的转移如下:
-
\(f_{i-1, j-a_i} \left ( j-a_i \ge 0 \right )\)。
-
\(f_{i-1, j+a_i} \left ( j+a_i \le len \right )\)。
时间复杂度:\(O(\sum n \max a \log_2 n)\)。
朴素实现:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define N 10005
#define mid (l + r >> 1)
int n, a[N];
bool F[N], G[N];
bool *f = F, *g = G;
void swap()
{
bool *t = f;
f = g, g = t;
}
bool check(int lim)
{
memset(f, 1, sizeof F);
for (int i = 1; i <= n; ++i)
{
swap();
memset(f, 0, sizeof F);
for (int j = 0; j <= lim; ++j)
{
if (j - a[i] >= 0)
f[j] |= g[j - a[i]];
if (j + a[i] <= lim)
f[j] |= g[j + a[i]];
}
}
for (int i = 0; i <= lim; ++i)
if (f[i])
return 1;
return 0;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%d", a + i);
int l = 1, r = 2000, it = -1;
while (l <= r)
check(mid)
? (it = mid, r = mid - 1)
: (l = mid + 1);
printf("%d\n", it);
}
return 0;
}
这个复杂度看起来有点不稳,可以试试 std::bitset(详见)。
#include <bits/stdc++.h>
#define int long long
#define mid (l + r >> 1)
using namespace std;
inline int read()
{
int f = 0, ans = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
ans = (ans << 3) + (ans << 1) + c - 48, c = getchar();
return f ? -ans : ans;
}
void write(int x)
{
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
const int N = 1e4 + 5, M = 2e3 + 5;
int n, a[N];
bitset<M> f, base;
inline bool check(int lim)
{
base.reset();
for (int i = 0; i <= lim; ++i)
base[i] = 1;
f = base;
for (int i = 1; i <= n; ++i)
f = f >> a[i] | f << a[i] & base;
return f.any();
}
signed main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
int T = read();
while (T--)
{
n = read();
for (int i = 1; i <= n; ++i)
a[i] = read();
int l = 1, r = 2000, it = -1;
while (l <= r)
check(mid)
? (it = mid, r = mid - 1)
: (l = mid + 1);
write(it), putchar('\n');
}
return 0;
}

浙公网安备 33010602011771号