排列组合的基本公式为:
实现A,C,并把他们封装称为一个函数,之后使用起来就会比较方便。
int A(int n, int m)
{
int res = 1;
for (int i = n; i > n - m; --i) {
res *= i;
}
return res;
}
int C(int n, int m)
{
int res = 1;
for (int i = n; i > n - m; --i) {
res *= i;
}
for (int i = 1; i <= m; ++i) {
res /= i;
}
return res;
}
1.方格移动
每次只能向左或者向下移动
方法一
class Robot {
public:
int countWays(int x, int y) {
// write code here
int dp[x][y];
for(int i = 0;i<x;++i){
dp[i][0] = 1;
}
for(int j = 0;j<y;++j){
dp[0][j] = 1;
}
for(int i = 1;i<x;++i){
for(int j = 1;j<y;++j){
dp[i][j] = dp[i-1][j]+dp[i][j-1];
}
}
return dp[x-1][y-1];
}
};
方法二
class Robot {
public:
int C(int n, int m)
{
int res = 1;
for (int i = n; i > n-m; --i) {
res *= i;
}
for (int i = 1; i <= m; ++i) {
res /= i;
}
return res;
}
int countWays(int x, int y) {
// write code here
--x;
--y;
return C(x+y, x);
}
};
2.站队问题
class StandInLine {
public:
int A(int n, int m)
{
int res = 1;
for (int i = n; i > n - m; --i) {
res *= i;
}
return res;
}
vector<int> getWays(int n, int a, int b) {
// write code here
vector<int> res;
res.push_back(A(n,n)/2);
res.push_back(A(n-1,n-1));
return res;
}
};
3.孤傲的A
A不能与b或者c相邻
class LonelyA {
public:
int A(int n, int m)
{
int res = 1;
for (int i = n; i > n - m; --i) {
res *= i;
}
return res;
}
int getWays(int n, int a, int b, int c) {
// write code here
int sum = A(n, n);
int sum1 = 2* 2 * A(n-1, n-1);
int sum2 = 2 * A(n-2, n-2);
return sum - sum1 + sum2;
}
};
4.分糖果
class Distribution {
public:
int C(int n, int m)
{
int res = 1;
for (int i = n; i > n-m; --i) {
res *= i;
}
for (int i = 1; i <= m; ++i) {
res /= i;
}
return res;
}
int getWays(int n, int m) {
// write code here
return C(n-1, m-1);
}
};
5.括号序列
class Parenthesis {
public:
int countLegalWays(int n) {
// write code here
return f(2*n)/f(n)/f(n)/(n+1);
}
long f(int n){
if(n == 0) return 1;
return n*f(n-1);
}
};
答案就是卡特兰数: