题解都在代码里了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
const ld PI=acos(-1);
const ld eps=1e-9;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const int seed=131;
const int M = 1e5+7;
ll dp[31][31][31][31][31];
/*i排安排ai,的方案数
必须满足a1>=a2>=a3>=a4>=a5 才有解
状态转移 : dp[a1][a2][a3][a4][a5] -> dp[a1+1][a2][a3][a4][a5]+=dp[a1][a2][a3][a4][a5]
a2<a1 dp[a1][a2][a3][a4][a5] -> dp[a1][a2+1][a3][a4][a5]+=dp[a1][a2][a3][a4][a5]
a3<a2 dp[a1][a2][a3][a4][a5] -> dp[a1][a2][a3+1][a4][a5]+=dp[a1][a2][a3][a4][a5]
a4<a3 dp[a1][a2][a3][a4][a5] -> dp[a1][a2][a3][a4+1][a5]+=dp[a1][a2][a3][a4][a5]
a5<a4 dp[a1][a2][a3][a4][a5] -> dp[a1][a2][a3][a4][a5+1]+=dp[a1][a2][a3][a4][a5]
本题可以通过状态转移后面的状态,或者计算一个状态怎么由前面状态转移2种方法
我写的是前面一种方法,后面的方法是比较常规的方法
从第一排开始往后安排学生,保证到一个状态时,它的状态已经转移完毕 ,且每个状态只跑一次
状态转移就像DAG一样,跑到一个点时,必须 保证所有连向当前点的点已经把状态转移到了当前点,
然后它再把状态转移给连向的点。
如果是后面一种方法,则必须保证,跑到一个点的时候,能到达当前点的 点 的状态已经全部更新。
初始dp[0][0][0][0][0]=1,其余为0;//因为全部由这个状态开始转移
*/
int s[6];
int main()
{
/*ios::sync_with_stdio(false);
cin.tie(0);*/
int k;
while(cin>>k&&k){
memset(dp,0,sizeof(dp));//初始化
memset(s,0,sizeof(s));
for(int i=1;i<=k;i++)
cin>>s[i];
dp[0][0][0][0][0]=1;
for(int a1=0;a1<=s[1];a1++)
for(int a2=0;a2<=s[2];a2++)
for(int a3=0;a3<=s[1];a3++)
for(int a4=0;a4<=s[4];a4++)
for(int a5=0;a5<=s[5];a5++){
if(a1<s[1])dp[a1+1][a2][a3][a4][a5]+=dp[a1][a2][a3][a4][a5];
if(a2<a1&&a2<s[2])dp[a1][a2+1][a3][a4][a5]+=dp[a1][a2][a3][a4][a5];
if(a3<a2&&a3<s[3])dp[a1][a2][a3+1][a4][a5]+=dp[a1][a2][a3][a4][a5];
if(a4<a3&&a4<s[4])dp[a1][a2][a3][a4+1][a5]+=dp[a1][a2][a3][a4][a5];
if(a5<a4&&a5<s[5])dp[a1][a2][a3][a4][a5+1]+=dp[a1][a2][a3][a4][a5];
}
cout<<dp[s[1]][s[2]][s[3]][s[4]][s[5]]<<endl;
}
return 0;
}