弧点的连接——线动态规划
/*
给定圆的周长上的n (n是偶数)个点,连接这些点并确保任意两条连接线不会交叉,并且每个点都与另一个点相连,
求总共有多少种连接方式。用动态规划求解。
输入描述.
输入第一行t表示测试用例的数量
对于每-一个测试用例,输入- -个偶数n表示圆上点的个数
输出描述
输出满足条件的连接方式的数量
样例输入
2
6
10
样例输出
5
42
*/
这里是引用
这是一个典型的线段dp问题,其实状态dp问题在大多情况下可以看作有一个集合变成另一个集合或者说一个状态变成另一个状态,以一种较为聪明的方式
/*
第一步是像下面的图片一样,确定集合的表现形式,明确目的:求出所有方案
这里的dp[n]表示n个点,有dp[n]种合法方案。
奇数个点的时候没有满足条件的方案所以返回0
下面我将在代码中进行精讲
*/
#include <bits/甩头dc++.h>
using namespace std;
int dp[1001];
int count(int m)
{
if (m == 0) return dp[m];
if (dp[m] != 0) return dp[m]; //如果状态已经被计算出来过那么就返回
for (int n = 2; n <= m; n++)
{
if (dp[n] != 0)continue;
//这一个循环代表 1连接哪一个点
for (int i = 1;i <= n ; i++)
{
if (i >= 2)dp[n] += dp[i - 2] * dp[n - i];
/*
* 当有n个点其实就是将,第一个点分别和第i个点相连,因为
* 连结的线段不能交叉所以可以通过第一个点和第i个点的连
* 线分成两部分,一部分是第1个点到第i个点中间的点,数
* 另一部分是第i个点到第1个点(顺时针)方向的点数。这
* 两部分的方案数乘积之和为所有的方案数
*/
}
}
return dp[m];
}
int main(){
int n;
int t;
dp[0] = 1; //在没有点的时候或者说只有0个点的时候,
//只有一种方案
for (int i = 1; i < 1001; i++) dp[i] = 0;
cin >> t;
for (int i = 0; i < t; i++) {
cin >> n;
if (n % 2 == 1) cout << 0 << "\n"; //这里表示,如果给出的点数是单数就返回0
else cout << count(n) << "\n";
}
}