NOIP 灯的排列问题

来源:互联网 发布:dwg mac 编辑:程序博客网 时间:2024/05/23 15:40

题目描述

设在一排上有N个格子(N≤20),若在格子中放置有不同颜色的灯,每种灯的个数记为N1,N2,……Nk(k表示不同颜色灯的个数)。

   放灯时要遵守下列规则:

①同一种颜色的灯不能分开;

②不同颜色的灯之间至少要有一个空位置。

   例如:N=8(格子数)

         R=2(红灯数)

         B=3(蓝灯数)

   放置的方法有:

      R-B顺序

R

R

 

B

B

B

 

 

R

R

 

 

B

B

B

 

R

R

 

 

 

B

B

B

 

R

R

 

B

B

B

 

 

R

R

 

 

B

B

B

 

 

R

R

 

B

B

B

   

      B-R顺序

B

B

B

 

R

R

 

 

B

B

B

 

 

R

R

 

B

B

B

 

 

 

R

R

 

B

B

B

 

R

R

 

 

B

B

B

 

 

R

R

 

 

B

B

B

 

R

R

    放置的总数为12种。

    程序要求:求排列总数。

输入格式

数据输入的方式为:

N

P1(颜色,为一个字母) N1(灯的数量)

P2 N2

……

Q(结束标记,Q本身不是灯的颜色)

 颜色和灯的数量之间由一个空格分隔。

输出

输出排列总数。

样例输入

8
R 2
B 3
Q

样例输出

12


注意同意颜色归到一起

暴力搜索出一种颜色顺序下的所有顺序

再将它乘上N种颜色的排列数N!

即可得到总排列数。。。。


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;struct color{    //没必要用结构体  开始想复杂了 数组就OK   char aa;   int bb;}q[10];int num=0,s;int sss=0;      //同意颜色顺序下排序数void dfs(int a,int b,int c)          //a表示已用颜色  b表示已放格子数  c表示是否要放空格{    if(a==num&&b==s)        {            sss++;            return;        }    if(b>s)        return;        if(c!=1)    dfs(a+1,b+q[a].bb,1);    dfs(a,b+1,0);}int main(){    int i,j;    int sum;    int ss=0;    char a;    int b;    scanf("%d",&s);    while(cin>>a&&a!='Q')    {        scanf("%d",&b);        ss=ss+b;        int t=0;        for(i=0;i<num;i++)          {              if(q[i].aa==a)                {                    q[i].bb+=b;                    t=1;                }          }          if(t==0)          {              q[num].aa=a;              q[num++].bb=b;          }    }    int per=1;    for(i=1;i<=num;i++)        per=per*i;    if(s-ss-num+1<=0)         //格子不够        cout<<0<<endl;    else    {        dfs(0,0,0);        cout<<sss*per<<endl;    }    return 0;}


0 0
原创粉丝点击