UVA 861 组合数学 递推
Posted stranger-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA 861 组合数学 递推相关的知识,希望对你有一定的参考价值。
题目链接 https://vjudge.net/problem/UVA-861
题意: 一个国际象棋棋盘,‘象’会攻击自己所在位置对角线上的棋子。问n*n的棋盘 摆放k个互相不攻击的 ‘象‘ 有多少种方式。
解析 :我们知道国际象棋的棋盘是黑交替 所以容易知道放在白格上的棋子 和 放在黑格上的棋子是不会互相攻击的。所以把白格和黑的分别拿出来讨论
相当于从白格里面拿i个 从黑格里面拿k-i个的方案数(0<=i<=k) 我们就开始处理从 白格 里面拿i个的方案数,我们把矩阵旋转45度看
W
B B
WWW
B B B B
WWWWW
B B B B
WWW
B B
W
然后调整一下
W
W
WWW
WWW
WWWWW
变成了这样 dp[ i ] [ j ] 表示 前 i 行放置 j 个棋子的方案数,假设第 i 行没有棋子,方案数就是dp[ i-1 ] [ j ], 假设 第 i 行 有 棋子 方案数就是dp[ i-1 ][ j-1 ] * ( a[ i ] - (i-1) ) ( a[ i ]表示当前
行的列数,减去前面被占用的行,就是当前行的选择数 ). 黑色格子一样.
代码
1 #include <bits/stdc++.h> 2 #define pb push_back 3 #define mp make_pair 4 #define fi first 5 #define se second 6 #define all(a) (a).begin(), (a).end() 7 #define fillchar(a, x) memset(a, x, sizeof(a)) 8 #define huan printf(" "); 9 #define debug(a,b) cout<<a<<" "<<b<<" "; 10 using namespace std; 11 typedef long long ll; 12 const int maxn=100,maxm=100,inf=0x3f3f3f3f; 13 const ll mod=1000000007; 14 ll a[maxn],b[maxn]; 15 ll dpa[maxn][maxn],dpb[maxn][maxn]; 16 int main() 17 { 18 int n,k; 19 while(cin>>n>>k) 20 { 21 if(n==0) 22 return 0; 23 fillchar(a,0); 24 fillchar(b,0); 25 fillchar(dpa,0); 26 fillchar(dpb,0); 27 int cnt1=1,cnt2=1; 28 for(int i=1;i<n;i++) 29 if(i%2==1) 30 { 31 a[cnt1++]=i; 32 a[cnt1++]=i; 33 } 34 for(int i=1;i<n;i++) 35 if(i%2==0) 36 { 37 b[cnt2++]=i; 38 b[cnt2++]=i; 39 } 40 if(n%2==0) 41 b[cnt2++]=n; 42 else 43 a[cnt1++]=n; 44 dpa[0][0]=1; 45 for(int i=1;i<cnt1;i++) 46 { 47 dpa[i][0]=1; 48 for(int j=1;j<=k;j++) 49 { 50 dpa[i][j]=dpa[i-1][j]+dpa[i-1][j-1]*(a[i]-j+1); 51 } 52 } 53 dpb[0][0]=1; 54 for(int i=1;i<cnt2;i++) 55 { 56 dpb[i][0]=1; 57 for(int j=1;j<=k;j++) 58 { 59 dpb[i][j]=dpb[i-1][j]+dpb[i-1][j-1]*(b[i]-j+1); 60 } 61 } 62 ll sum=0; 63 for(int i=0;i<=k;i++) 64 { 65 sum+=dpa[cnt1-1][i]*dpb[cnt2-1][k-i]; 66 } 67 cout<<sum<<endl; 68 } 69 }
以上是关于UVA 861 组合数学 递推的主要内容,如果未能解决你的问题,请参考以下文章
uva 1478 - Delta Wave(递推+大数+卡特兰数+组合数学)