POJ 1664 放苹果(DFS)

POJ 1664 放苹果(DFS)

http://poj.org/problem?id=1664

题意: 

       把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

分析:

       注意到盘子是一样的,方法5 1 1 和1 5 1 只能算一种.所以我们需要给每个盘子放的苹果数定序.

       也就是说我们从少往多放,即我们从1号盘子开始放,我们可以放0-M个苹果,但是我们要保证2号盘子中放的苹果数>=1号盘子中放的苹果数,3号,4号,…N号盘子也一样.

       但是这样的话,可能放到后面我们就没有苹果放了,这样违反了我们苹果从少往多放的原则,所以我们打算把苹果从多往少放.即如果我1号盘子里放了4个苹果,那么2号到N号盘子的苹果数只能<=4了.

       在源代码的dfs中由下面这句:

else for(int i = min(num, left);i >= (left-1)/(n-cnt)+1; i--)

       其中i表示当前盘子将要放的苹果数,既然上一个盘子放了num个苹果,i肯定要<=num了,且剩余left个苹果,所以i初值= min(num, left) 表示i能取到的最大值。

       但是i能取的最小值是多少呢?i能直接取0吗?如果left>0的话,i不能取0。因为如果这个i取0,后面的盘子都得为0,当前剩余的left个苹果就没地方放了。left不为0时,i能取的最少值为:上取整(剩余苹果数/剩余盘子数)也就是(left-1)/(n-cnt)+1。注意这里要求left>=1。

       如果left为0的话,i只能取0。

AC代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int m,n;
int ans;//最终解
void dfs(int cnt,int left,int num)//当前已放cnt个盘子,还剩left个苹果且上把放了num个苹果,从多往少放
{
    if(cnt==n&&left==0) ans++;
    else if(left==0) ans++;
    else for(int i = min(num, left); i >= (left-1)/(n-cnt)+1; i--)//left>0时
        dfs(cnt+1,left-i,i);
}
int main()
{
    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&m,&n);
        ans=0;
        dfs(0,m,100000);
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值