标签:
题目是在n*n的棋盘上放k个车使其不互相攻击的方案数。
首先可以明确的是n*n最多只能合法地放n个车,即每一行都指派一个列去放车。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 long long d[31][31]; 5 int main(){ 6 int t,n,k; 7 scanf("%d",&t); 8 for(int cse=1; cse<=t; ++cse){ 9 scanf("%d%d",&n,&k); 10 if(k>n){ 11 printf("Case %d: 0\n",cse); 12 continue; 13 } 14 memset(d,0,sizeof(d)); 15 d[0][0]=1; 16 for(int i=0; i<n; ++i){ 17 for(int j=0; j<=k; ++j){ 18 d[i+1][j]+=d[i][j]; 19 if(j<k) d[i+1][j+1]+=d[i][j]*(n-j); 20 } 21 } 22 printf("Case %d: %lld\n",cse,d[n][k]); 23 } 24 return 0; 25 }
另外在别人博客看到排列组合的解法:结果就是C(n,k)*A(n,k),即从n行中选出k行来放车,然后这k行要指派的列就是从n列中选出k列的排列。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 long long C[31][31]; 5 int main(){ 6 for(int i=0; i<31; ++i) C[i][0]=1; 7 for(int i=1; i<31; ++i){ 8 for(int j=1; j<=i; ++j) C[i][j]=C[i-1][j-1]+C[i-1][j]; 9 } 10 int t,n,k; 11 scanf("%d",&t); 12 for(int cse=1; cse<=t; ++cse){ 13 scanf("%d%d",&n,&k); 14 if(k>n){ 15 printf("Case %d: 0\n",cse); 16 continue; 17 } 18 long long res=C[n][k]; 19 for(int i=0; i<k; ++i) res*=n-i; 20 printf("Case %d: %lld\n",cse,res); 21 } 22 return 0; 23 }
标签:
原文地址:http://www.cnblogs.com/WABoss/p/5176294.html