思路
\(1=<k<= 5\),所以最多会有五个位置,五个位置分配人,即集合为f[a][b][c][d][e]表示五个位置各放了a, b, c, d, e个人的方法的数量,同时h[1]>=h[2]>=h[3]>=h[4]>=h[5],所以后面的层也可以取到和上面一层一样的人数,但是不能超过,因此b<= min(a, s[2])
我们考虑最后一个同学的位置,其实就是五个位置都考虑一下,因此我们需要满足这一层人数减去1也大于等于下一层,那样就可以放在当前位置,同时该层得为正数,不然例如a-1如果小于0就要段错误了
ps: 数据还挺极限的,这f开到f[35][35][35][35][35]就寄了,如果是是32就不会超时,应该是memset上花了很多时间
#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define all(x) (x).begin(), (x).end()
#define SZ(x) (int) (x).size()
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
typedef vector<int> VI;
typedef double db;
const int N = 32;
int n, s[10];
ll f[N][N][N][N][N];
void solve() {
memset(s, 0, sizeof(s));
for (int i = 1; i <= n; i++) cin >> s[i];
memset(f, 0, sizeof(f));
f[0][0][0][0][0] = 1; // 哪里都不放人只有一种选择
for (int a = 0; a <= s[1]; a++) {
for (int b = 0; b <= min(a, s[2]); b++) {
for (int c = 0; c <= min(b, s[3]); c++) {
for (int d = 0; d <= min(c, s[4]); d++) {
for (int e = 0; e <= min(d, s[5]); e++) {
ll &x = f[a][b][c][d][e];
if (a && a-1 >= b) x += f[a-1][b][c][d][e];
if (b && b-1 >= c) x += f[a][b-1][c][d][e];
if (c && c-1 >= d) x += f[a][b][c-1][d][e];
if (d && d-1 >= e) x += f[a][b][c][d-1][e];
if (e) x += f[a][b][c][d][e-1];
}
}
}
}
}
cout << f[s[1]][s[2]][s[3]][s[4]][s[5]] << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
// int tt;
// cin >> tt;
while (cin >> n, n) {
solve();
}
return 0;
}
标签:typedef,int,memset,35,照相,271,&&,AcWing,define
From: https://www.cnblogs.com/chelly-algorithm/p/16826898.html