PC/UVa:110803/10128
英文题目不好理解,去网上查了一下,意思就是说N
个身高不一样的人排成一列,从左边看可以看到P
个人,从右边看可以看到R
个人,求总的排列数目。
最开始想的是用组合公式,N
个人中最高的那个人将队列分成了两部分,左边i
个人,从左看可以看见P - 1
个人(右边看见多少都行),右边N - 1 - i
个人,从右看可以看见R - 1
个人(左边看见多少都行),根据乘法原理,两部分相乘,再乘上C(N - 1, i)
(最开始想的时候忘记了乘组合数)得到总排列数目,所以问题就变成了给定i
个人,从左可以看见j
个人的排列方式有多少种。
这个排列数目应该是能递推的。当i - 1
个人排好之后,如果第i
个人最矮,那么放在最左边,j
增加1
,其余情况j
不变,也就是说公式为g[i][j] = g[i - 1][j - 1] + (i - 1) * g[i - 1][j]
。如果第i
个人不是最矮,那么可以通过更改前i
个人的选择顺序,使得第i
个人最矮。
这一点特别重要。如果第i
个人的身高可以是任意高度,那么就不能保证在前边的每一种排列方法基础上排第i
个人时,所有情况都是等效的,也就是不满足无后效性。
注意这种方法的边界条件g[0][0] = 0
。
然后还有第二种方法。那就是直接用三维数组表示解,f[n][p][r] = f[n - 1][p - 1][r] + f[n - 1][p][r - 1] + (n - 2) * f[n - 1][p][r]
。当第i
个人最矮时,TA在最左边则p
增加1
,在最右边则r
增加1
,其余位置不变。
注意这种方法的边界条件f[1][1][1] = 1
。
#include <iostream>
#define MAX_N 13 + 1
using namespace std;
void count1(int T)
{
/*
g[i][j] = g[i - 1][j - 1] + (i - 1) * g[i - 1][j]
*/
unsigned long long C[MAX_N][MAX_N] = { 0 }, g[MAX_N][MAX_N] = { 0 };
g[0][0] = 1;
for (int i = 1; i < MAX_N; i++)
{
for (int j = 1; j <= i; j++)
{
g[i][j] = g[i - 1][j - 1] + (i - 1) * g[i - 1][j];
}
}
/*
C[n][k] = C[n - 1][k] + C[n - 1][k - 1]
*/
C[0][0] = 1;
for (int n = 1; n < MAX_N; n++)
{
C[n][0] = 1;
for (int k = 1; k <= n; k++)
{
C[n][k] = C[n - 1][k] + C[n - 1][k - 1];
}
}
//1 2 3 4 5 6 7 8 9 10
int N = 0, P = 0, R = 0;
for (int t = 0; t < T; t++)
{
cin >> N >> P >> R;
unsigned long long ull = 0;
for (int m = P; m <= N + 1 - R; m++)
{
ull += g[m - 1][P - 1] * g[N - m][R - 1] * C[N - 1][m - 1];
}
cout << ull << endl;
}
}
void count2(int T)
{
/*
f[n][p][r] =
f[n - 1][p - 1][r] +
f[n - 1][p][r - 1] +
(n - 2) * f[n - 1][p][r]
*/
unsigned long long f[MAX_N][MAX_N][MAX_N] = { 0 };
f[1][1][1] = 1;
for (int n = 2; n < MAX_N; n++)
{
for (int p = 1; p < MAX_N; p++)
{
for (int r = 1; r < MAX_N; r++)
{
f[n][p][r] =
f[n - 1][p - 1][r] +
f[n - 1][p][r - 1] +
(n - 2) * f[n - 1][p][r];
}
}
}
int N = 0, P = 0, R = 0;
for (int t = 0; t < T; t++)
{
cin >> N >> P >> R;
cout << f[N][P][R] << endl;
}
}
int main()
{
int T = 0;
cin >> T;
count2(T);
return 0;
}
/*
3
10 4 4
11 3 1
3 1 2
*/