给两个皇后找位置(数学递推)
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 }