传送门:
描述:
题意:
给你n个点,将这些点放在一个环上,问你不相交的连k条线的方案数。(没有重点)
思路:
dp[i][j]表示i个点连j条线的方案数,那么新加一个点i,
情况1:i没有和之前的点相连,方案数为dp[i-1][j];
情况2:i和p号点相连(0<p<j),那么就i-p这条线把所有点划分成两部分,然后枚举一些子问题的连边数,方案数为sum( dp[p-1][q]*dp[i-1-p][j-1-q] ) (0<=q<j)
复杂度:
O(n^4)
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll __int64
#define rep(i,k,n) for(int i=k;i<=n;i++)
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
if(!p) { puts("0"); return; }
while(p) stk[++ tp] = p%10, p/=10;
while(tp) putchar(stk[tp--] + '0');
putchar('\n');
}
ll dp[50][50];
int main(){
int k,n;
read(n),read(k);
rep(i, 0, n)dp[i][0] = 1;
rep(i, 1, n){
rep(j, 0, k){
dp[i][j] = dp[i-1][j];
rep(p, 1, i-1){
rep(q, 0, j-1){
dp[i][j] += dp[p-1][q] * dp[i-1-p][j-1-q];
}
}
}
}
print(dp[n][k]);
return 0;
}