CodeForces 1927G Paint Charges
看到 考虑 dp。发现从左向右决策,因为一个点可以向左或向右覆盖,所以需要记最靠左的未覆盖的位置 和最靠右的已覆盖位置 ,状态就是 ,dp 最小的覆盖次数。
转移的讨论很简单。考虑不覆盖还是向左或向右覆盖,若向左或向右覆盖看能否覆盖到 或 。这样转移是 的。总时间复杂度 。
code
// Problem: G. Paint Charges // Contest: Codeforces - Codeforces Round 923 (Div. 3) // URL: https://codeforces.com/contest/1927/problem/G // Memory Limit: 256 MB // Time Limit: 4000 ms // // Powered by CP Editor (https://cpeditor.org) #include <bits/stdc++.h> #define pb emplace_back #define fst first #define scd second #define mkp make_pair #define mems(a, x) memset((a), (x), sizeof(a)) using namespace std; typedef long long ll; typedef double db; typedef unsigned long long ull; typedef long double ldb; typedef pair<ll, ll> pii; const int maxn = 110; int n, a[maxn], f[maxn][maxn][maxn]; void solve() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); } mems(f, 0x3f); f[0][1][0] = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n + 1; ++j) { for (int k = 0; k <= n; ++k) { f[i][j][k] = min(f[i][j][k], f[i - 1][j][k]); if (max(i - a[i] + 1, 1) <= j && j <= i) { int nk = max(i, k); f[i][nk + 1][nk] = min(f[i][nk + 1][nk], f[i - 1][j][k] + 1); } int nk = min(i + a[i] - 1, n); if (nk > k) { int nj = (i <= j && j <= nk ? nk + 1 : j); f[i][nj][nk] = min(f[i][nj][nk], f[i - 1][j][k] + 1); } } } } printf("%d\n", f[n][n + 1][n]); } int main() { int T = 1; scanf("%d", &T); while (T--) { solve(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具