您的位置:首页 > 其它

[ACM] hdu 1521 排列组合(组合+DFS)

2014-04-06 23:16 417 查看

排列组合

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 2119 Accepted Submission(s): 875



[align=left]Problem Description[/align]

有n种物品,并且知道每种物品的数量。要求从中选出m件物品的排列数。例如有两种物品A,B,并且数量都是1,从中选2件物品,则排列有"AB","BA"两种。

[align=left]Input[/align]

每组输入数据有两行,第一行是二个数n,m(1<=m,n<=10),表示物品数,第二行有n个数,分别表示这n件物品的数量。

[align=left]Output[/align]

对应每组数据输出排列数。(任何运算不会超出2^31的范围)

[align=left]Sample Input[/align]

2 2
1 1


[align=left]Sample Output[/align]

2


[align=left]Author[/align]

xhd

解题思路:

从n个物品里面选m个,n个物品里面有相同的。记得有一个公式 比如AAABB 那么这五个字母的总排列数为 5! / (2! *3 !) 2 3为重复度。比赛的时候就是根据这个写的。有n种不同的物品,每种有不同的个数,要求在总物品里面取m个排列有多少。问题的关键是 重复的物品是来自哪个种类的。比如要取5件物品,可能3件相同来自同一种物品,2件相同。也可能五件都不相同。所以用DFs广搜,每种物品取多少个相加起来等于m。按照这种思路Ac了。

赛后看了网上这题是用指数型母函数做的,今天太晚了,明天再研究。

代码:

#include <iostream>
#include <string.h>
using namespace std;

int jie(int n)
{
int sum=1;
for(int i=1;i<=n;i++)
sum*=i;
return sum;
}

int num[11];
int count[11];
int n,m,up,zong;

void dfs(int p)
{
int sum=0;
for(int i=1;i<p;i++)
{
sum+=count[i];
}
if(sum==m)
{
int temp=up;
for(int i=1;i<p;i++)
{
temp/=jie(count[i]);
}
zong+=temp;
return;
}
if(p>n)
return;
for(int i=0;i<=num[p];i++)
{
count[p]=i;
dfs(p+1);
}

}
int main()
{
while(cin>>n>>m)
{
int sum=0;
memset(count,0,sizeof(count));
for(int i=1;i<=n;i++)
{
cin>>num[i];
sum+=num[i];
}
up=jie(m);
zong=0;
dfs(1);
cout<<zong<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: