9286:盒子与小球之四
-
总时间限制:
- 1000ms 内存限制:
- 131072kB
-
描述
-
给定N个各不相同的小球,和M个不同的BOX,有多少种不同的放球方法,使得每个BOX里的小球个数不小于K。N,M,K均小于15
输入
-
每行给出N,M,K
以0 0 0结束
输出
-
如题
样例输入
-
3 3 1 2 4 1 3 2 0 0 0 0
样例输出
-
6 0 8
题解:dp
这道题与 poj
Push Botton Lock 一题很像。
但是那道题每个盒子没有个数限制,且没有空盒子。物品与盒子都是不同的。
当时做那道题的时候是考虑的最后一个盒子放几个以及放哪些。
f[i][j]表示将i个球放到j个盒子中的方案数。
f[i][j]=sigma(f[i-k][j-1]*c[n-(i-k)][k]) 这道题也可用同样的方式思考。只是枚举k的时候注意一下个数限制。因为可以存在不止一个空盒子,所以我们枚举i的时候最小值不一定是1.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 30
#define LL long long
using namespace std;
int n,m,k;
LL f[N][N],c[N][N];
void calc()
{
for (int i=0;i<=20;i++) c[i][0]=1;
for (int i=1;i<=20;i++)
for (int j=1;j<=i;j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
}
int main()
{
calc();
while(true){
scanf("%d%d%d",&n,&m,&k);
if (n==0&&m==0&&k==0) break;
memset(f,0,sizeof(f));
for (int i=k;i<=n;i++)
f[i][1]=c[n][i];
for (int i=k;i<=n;i++)
for (int j=2;j<=m;j++)
{
if(i<j*k) break;
for (int l=k;l<=n;l++)
{
if (i-l<0) break;
f[i][j]+=f[i-l][j-1]*c[n-(i-l)][l];
}
}
cout<<f[n][m]<<endl;
}
}