您的位置:首页 > 其它

PID371 / [AHOI1997]彩旗飘飘 排列组合加DP

2016-02-21 14:44 197 查看
题目描述

有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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: