题意:
给定顶点数L,求L个顶点围成的多边形的角度字符串有多少个不同的
分析:
XJB分析,开始4个顶点可以围成唯一的一个,替换掉其中的一个R,只能用ROR去替换,才能使其封闭,那么只有从4开始的偶数才有解,且O的数量为 :(L-4)/ 2,R的数量为:L - (L-4) / 2
简化成:给定x个O和y个R,求组成的字符串有多少个,且满足不能有两个O相连(首尾也要算)
方法1:排列组合
考虑在y个R的排列的空隙中插入x个O,要考虑首尾相邻的情况
(1)尾插入O,则首不能插入O:
那么剩余x-1个O,y-1个空隙可用的方案为:
(2)尾不插入O:
那么剩余x个O,y个空隙可用的方案为:
答案为:
方法2:动态规划
定义dp[i][j][k][R/O][O/R],表示前i个位置中用了j个O,k个R,首为R/O,尾为O/R的方案数,
初始化:dp[2][1][1][0][1] = 1;dp[2][1][1][1][0] = 1; dp[2][0][2][1][1] = 1;从3开始递推,开滚动数组优化即可
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL dp[2][1005][1005][2][2];
int main()
{
int T = 1,n;
while(cin >> n && n)
{
printf("Case %d: ",T++);
if(n&1 || n < 4)
{
cout << 0 << '\n';
continue;
}
int x = (n-4) / 2; //O : 0
int y = n - x; //R : 1
dp[0][1][1][0][1] = 1;
dp[0][1][1][1][0] = 1;
dp[0][0][2][1][1] = 1;
for(int i = 3; i <= n; ++i)
{
int q = i&1,p = (i-1)&1;
for(int j = 0; j <= x; ++j)
{
int k = i - j;
if(k){
dp[q][j][k][0][1] = dp[p][j][k-1][0][0]+dp[p][j][k-1][0][1];
dp[q][j][k][1][1] = dp[p][j][k-1][1][0]+dp[p][j][k-1][1][1];
}
if(j){
dp[q][j][k][1][0] = dp[p][j-1][k][1][1];
dp[q][j][k][0][0] = dp[p][j-1][k][0][1];
}
}
}
cout << dp[n&1][x][y][0][1] + dp[n&1][x][y][1][0] + dp[n&1][x][y][1][1]<< '\n';
}
return 0;
}