有n面红旗和n面黄旗从东到西插成一排。如果相邻的两面旗帜的颜色不同,则称为颜色发生一次改变。
任务:计算这2n面旗帜的颜色改变m次的插法共有多少种?
示例:
旗帜的颜色为“红黄红红黄黄黄”称为颜色改变了3次的插法。
在n=4,m=1时仅有两种插法:“红红红红黄黄黄黄”和“黄黄黄黄红红红红”,对应的输出为“2”。
输入:从键盘上依闪输入自然数n和m。(n<15)
输出:把插法总数在屏幕上显示输出。
插排法
黄色已经排成一排然后向里面插入红色发现插入两边的变化数+1插入中间变化数+2,所以如果m为偶数为只插入中间和两边都插得和奇数为两边只插一个的和,然后DP把剩下的棋子插入即可
#include<iostream>
using namespace std;
int dp[20][20]={0};
int C(int n,int m);
int main()
{
int n=0,m=0;
for(int i=0;i<=15;i++)
{
dp[1][i]=1;
dp[i][0]=1;
dp[i][1]=i;
}
for(int i=2;i<=15;i++)
{
for(int j=0;j<=15;j++)
{
int temp=0;
for(int k=0;k<=j;k++)
{
temp+=dp[i-1][j-k];
}
dp[i][j]=temp;
}
}
while(cin>>n>>m)
{
int sum=0;
if(m&1)
{
sum=sum+2*(C(n-1,(m-1)/2)*dp[1+(m-1)/2][n-1-(m-1)/2]);
}
else
{
sum+=(C(n-1,m/2)*dp[m/2][n-m/2]);
sum+=(C(n-1,m/2-1)*dp[m/2+1][n-m/2-1]);
}
cout<<sum<<endl;
}
return 0;
}
int C(int n,int m)
{
int a=1,b=1;
for(int i=1;i<=m;i++)
{
a*=i;
b*=(n-m+i);
if(b%a==0)
{
b/=a;
a=1;
}
}
return b;
}