Chess Queen UVA - 11538 象棋中的皇后 排列组合问题

版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/qq_42835910/article/details/90142026

在2x2 棋盘上放两个相互攻击的皇后( 一白一黑) , 一共有12 种方法,如图2-1 所示。
图2 -1
如果棋盘是nXm 的,有多少种方法放置两个相互攻击的皇后?例如n=1 00, m=223 时答案为10 907 100 。
【输入格式】
输入由不超过5000 行组成,每行均为-组数据,包含两个整数n, m (0 运n,m~二10勺。输入结束标志为n=m=O 。
【输出格式】
对于每组数据,输出在nXm 棋盘上放两个相互攻击的皇后的方案数。输出保证不超过64 位带符号整数的范围。
【分析】
因为只有两个皇后,因此相互攻击的方式只有两个皇后在同一行、同一列或同一对角线3 种情况。这3 种情况没有交集,因此可以用加法原理。设在同一行放两个皇后的方案数为A(n,m) ,同一列放两个皇后的方案数为B(n ,时,同一对角线放两个皇后的方案数为D(n ,m) ,则答案为A(n ,m)+B(n,m)+D(n ,m) 。

A(n ,m)的计算可以用乘法原理:放自后有nm 种方法,放黑后有m-l 种方法,相乘就是nm(m-1) 。也可以理解为先选一行(有n 种方法) ,然后在这一行中选两个位置做全排列,因此有m(m-1)种方案。根据乘法原理得到nm(m-1) 。
B(n ,m)其实就等于A(m,n) ( 想一想,为什么) , 也就是mn(n-1) 。

求D(n ,m)的思考过程会稍微麻烦一些。不妨设n运m , 所有/向的对角线,从左到右的长度依次为   

                                    
考虑到还有另一个方向的对角线,上面的整个结果还要乘以2 ,即

                 
程序如下。 

#include <iostream>
#include <algorithm>
using namespace std;

int main(int argc, char** argv) {
	unsigned long long n, m; // 最大可以保存2^64-1>1.8*10^19
	while( cin>> n>> m && (n || m)){
		if(n > m) swap(n,m); // 这样就避免了对n<=m和n>m两种情况分类讨论
		cout<< n*m*(m-1) + m*n*(n-1) + 2*n*(n-1)*(3*m-n-1)/3 << "\n";
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42835910/article/details/90142026
今日推荐