SP15637 GNYR04H - Mr Youngs Picture Permutations(线性 dp)

题目

求方案数,考虑 dp

—— 状态设计和边界 ——

题目告诉了一个很显然的性质:

  • 每一排从左至右保证高度单调递减
  • 每一列从后往前保证高度单调递减

那么可以发现,对于每一行,每一列,一定是按高度顺序插入,并且是连续插入,因为如果不连续,就无法保证单调递减的性质

同时,它给出了另一个性质 : N1N2Nkk 排, Ni 为每排长度)

可以总结出,它总是满足这样一个轮廓:

image

可以设计状态维护这个东西,考虑 k[1,5]

则定义 fa,b,c,d,e 表示 1 ~ 5 行分别的同学数为 a ~ e 时的方案数。

边界:当没有同学时,显然是一种方案,即 f0,0,0,0,0=1 .

—— 状态转移方程 ——

考虑当前状态 fa,b,c,d,e 可以由插入 a ~ e 中任意一个转移过来,但要保证后一排的长度不小于前一排这一前提,则有:

fa,b,c,d,e=fa,b,c,d,e +{fa1,b,c,d,ea>0,a1bfa,b1,c,d,eb>0,b1cfa,b,c1,d,ec>0,c1dfa,b,c,d1,ed>0,d1efa,b,c,d,e1e>0

—— 阶段和答案 ——

暴力枚举五层的数量,同时注意对于 2 ~ 5 层,要保证长度不大于前一层,取个 min 就可以了。

由于是求累加的方案数,那么答案肯定是出现在最大集合,即 fN1,N2,N3,N4,N5

—— 时间复杂度 ——

数据这么小,没必要算什么复杂度了吧 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;
}
posted @   Zhang_Wenjie  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示