SP15637 GNYR04H - Mr Youngs Picture Permutations(线性 dp)
求方案数,考虑 dp
—— 状态设计和边界 ——
题目告诉了一个很显然的性质:
- 每一排从左至右保证高度单调递减
- 每一列从后往前保证高度单调递减
那么可以发现,对于每一行,每一列,一定是按高度顺序插入,并且是连续插入,因为如果不连续,就无法保证单调递减的性质
同时,它给出了另一个性质 :
可以总结出,它总是满足这样一个轮廓:
可以设计状态维护这个东西,考虑
则定义
边界:当没有同学时,显然是一种方案,即
—— 状态转移方程 ——
考虑当前状态
—— 阶段和答案 ——
暴力枚举五层的数量,同时注意对于 2 ~ 5 层,要保证长度不大于前一层,取个 min 就可以了。
由于是求累加的方案数,那么答案肯定是出现在最大集合,即
—— 时间复杂度 ——
数据这么小,没必要算什么复杂度了吧 qwq
#include <bits/stdc++.h> #define re register int #define min(x, y) (x < y ? x : y) using namespace std; typedef long long ll; const int N = 31; int n, h[10]; ll f[N][N][N][N][N]; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); while (cin >> n, n) { memset(f, 0, sizeof f); memset(h, 0, sizeof h); for (re i = 1; i <= n; i ++) cin >> h[i]; f[0][0][0][0][0] = 1; for (re a = 0; a <= h[1]; a ++) for (re b = 0; b <= min(h[2], a); b ++) for (re c = 0; c <= min(h[3], b); c ++) for (re d = 0; d <= min(h[4], c); d ++) for (re e = 0; e <= min(h[5], d); e ++) { ll val = f[a][b][c][d][e]; if (a && b <= a - 1) val += f[a - 1][b][c][d][e]; if (b && c <= b - 1) val += f[a][b - 1][c][d][e]; if (c && d <= c - 1) val += f[a][b][c - 1][d][e]; if (d && e <= d - 1) val += f[a][b][c][d - 1][e]; if (e) val += f[a][b][c][d][e - 1]; f[a][b][c][d][e] = val; } cout << f[h[1]][h[2]][h[3]][h[4]][h[5]] << '\n'; } return 0; }
分类:
E 动态规划 - 线性 dp
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具