271. 杨老师的照相排列 ###K ###K //K
题目链接:https://www.acwing.com/problem/content/273/
思路: 考虑按照1 2 3 递增来放数字, 每次如果要放一个数字,要保证左边一个位置一定要有
数字并且上面一个位置一定要有数字,否则后面的数字不管怎么放 都会不满足题意
dp[i][j][k][x][y] 为第1~5行放多少个数字的合法方案 划分子集的依据为 最后一个数放在了第几排,
注意 一定要满足 j<=i k<=j 这样的条件 不然可能又非法状态转移过来
所以 u+=dp[i-1][j][k][x][y] …… dp[i][j][k][x][y-1]
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e3+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define ull unsigned long long 7 #define pi pair<int,int> 8 #define fi first 9 #define sc second 10 #define pb push_back 11 12 ll dp[31][31][31][31][31]; 13 int a[6]; 14 15 16 int main() 17 { 18 ios::sync_with_stdio(false); 19 cin.tie(0); 20 int n; 21 while(cin>>n,n) 22 { 23 memset(a,0,sizeof(a)); 24 for(int i=1;i<=n;i++) cin>>a[i]; 25 dp[0][0][0][0][0]=1; 26 for(int i=1;i<=a[1];i++) 27 { 28 for(int j=0;j<=i;j++) 29 { 30 for(int k=0;k<=j;k++) 31 { 32 for(int x=0;x<=k;x++) 33 { 34 for(int y=0;y<=x;y++) 35 { 36 ll &u=dp[i][j][k][x][y]; 37 u=0; 38 if(i) u+=dp[i-1][j][k][x][y]; 39 if(j) u+=dp[i][j-1][k][x][y]; 40 if(k) u+=dp[i][j][k-1][x][y]; 41 if(x) u+=dp[i][j][k][x-1][y]; 42 if(y) u+=dp[i][j][k][x][y-1]; 43 } 44 } 45 } 46 } 47 } 48 cout<<dp[a[1]][a[2]][a[3]][a[4]][a[5]]<<'\n'; 49 } 50 51 52 53 54 55 56 57 58 }