openjudge 9286:盒子与小球之四 (dp)

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值