给两个皇后找位置(数学递推)

UVA 11538

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2533

题解:在n * m的棋盘上给两个皇后找位置。横着找,竖着找,斜着找。

先说个简单的东西:在一行n个棋盘给两个皇后找位置,确定一个皇后,再给另一个皇后找位置。第一个皇后有n个位置可选 ,确定后第二个皇后有n - 1个位置可选,所以总共有 n* (n - 1)种解。

然后我们可以将这个问题转化为寻找棋盘上有多少这样的行,每行有多少个位置,就简单了。

先预处理一下,将 i 个格子有  i * (i - 1)种解法存在数组 a[i] 中。

 

先横着找:一行m个位置,共n行,所以有 n * a[m]种解法。

再竖着找:一列n个位置,共m列,所以有 m * a[n]种解法。

斜着找:这个就稍微麻烦一些了,不过没关系,慢慢来。

         先找个规律:从左上角开始画倾斜角为45度的斜线,我们可以发现,这些斜线经过的格子个数有个规律:1,2,3,4,···,n - 1,n ······n,n - 1,···,4,3,2,1

         所以我们可以写个从1到 n - 1的循环,将每条斜线对应的解的个数相加,结果  * 2,就是两头不相等斜线的解了。

         接着考虑中间有多少个n ,画图很容易发现是 (m - n) + 1 个。

         注意!这两个结果相加的解仅仅是一个方向的,还有倾斜角为135度的情况,所以这两个结果相加 * 2才是斜着找最后的结果。

最后,将三种找法的结果相加即为所求。

 

代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<stack>
 7 #define ll long long
 8 using namespace std;
 9 
10 ll a[1000005] = {0};
11 
12 int main()
13 {
14     
15     a[1] = 0;
16     for(ll i = 2; i <= 1000000; i++)
17     {
18         a[i] = i * (i - 1);
19     }
20     
21     ll n, m;
22     while(cin >> n >> m && n && m)
23     {
24         if(n > m) swap(n, m);
25         ll ans = m * a[n];//竖着放 
26         ans += n * a[m];//横着放 
27         ans += (m - n + 1) * 2 * a[n];//斜着放而且是斜向格子数==n时 
28         for(ll i = 2; i < n; i++)
29         {
30             ans +=  2 * 2 * a[i];//斜着放的不相等斜线
31         }
32         
33         cout << ans << endl;
34     }
35     return 0;
36 }

 

posted @ 2019-08-15 21:15  小夯货  阅读(154)  评论(0编辑  收藏  举报