题目描述
设在一排上有N个格子(N≤20),若在格子中放置有不同颜色的灯,每种灯的个数记为N1,N2,……Nk(k表示不同颜色灯的个数)。放灯时要遵守下列规则:
①同一种颜色的灯不能分开;
②不同颜色的灯之间至少要有一个空位置。
例如:
N=8(格子数)
R=2(红灯数)
B=3(蓝灯数)
放置的方法有:
R-B顺序
![](https://img-blog.csdn.net/20170224161245850?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXhnXzEyMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
B-R顺序
![](https://img-blog.csdn.net/20170224161338679?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXhnXzEyMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
放置的总数为12种。
程序要求:求排列总数。
输入格式
数据输入的方式为:
N
P1(颜色,为一个字母) N1(灯的数量)
P2 N2
……
Q(结束标记,Q本身不是灯的颜色)
颜色和灯的数量之间由一个空格分隔。
输出
输出排列总数。样例输入
8
R 2
B 3
Q
样例输出
12
题解:
记录方案的dfs:http://www.cnblogs.com/qscqesze/p/4334157.html
注意同一颜色归到一起
dfs出一种颜色顺序下的所有顺序
再将它乘上N种颜色的排列数N!
即可得到总排列数。。。。
dfs出一种颜色顺序下的所有顺序
再将它乘上N种颜色的排列数N!
即可得到总排列数。。。。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mem(a) memset(a,0,sizeof(a))
#define mp(x,y) make_pair(x,y)
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
inline ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
//
const int maxn = 1e5+10;
int n,s,num,k;
char c;
struct node{
char x;
int y;
}q[maxn];
void dfs(int a,int b,int c){ //a表示已用颜色 b表示已放格子数 c表示是否要放空格
if(a==num && b==n){
k++; //同一颜色顺序下排序数
return ;
}
if(b > n) return ;
if(!c) dfs(a+1,b+q[a].y,1);
dfs(a,b+1,0);
}
int main(){
n = read();
while(cin>>c, c!='Q'){
int b = read();
s += b;
bool f = 0;
for(int i=0; i<num; i++){
if(q[i].x == c){
q[i].y += b;
f = 1;
}
}
if(!f){
q[num].x = c;
q[num++].y += b;
}
}
int per=1;
for(int i=1; i<=num; i++)
per = per*i;
if(n - (s+num-1) <= 0) { //格子不够
puts("0");
return 0;
}else{
dfs(0,0,0);
cout << per*k << endl;
}
return 0;
}