[dp]poj1664 放苹果 dp解法


放苹果
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 27747 Accepted: 17550

Description

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

Input

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

Output

对输入的每组数据M和N,用一行输出相应的K。

Sample Input

1
7 3

Sample Output

8

这道题目除了用dp做以外,还可以用很多其他的方法过。因为题目数据非常小,各路大牛的博客上有层出不穷的解法,我见过的有可以用DFS递归的方法,组合数学的方法,还有暴力打表法……今天来探讨一下使用dp做的方法。


拿到题目一看,很容易想到用dp[i][j] 表示共i个苹果放入j个盘子的方法。

状态转移的过程一看好像很多。不知如何构建,但是我们可以从目标状态入手!把i个苹果放入j个盘子里的情况无非有两种

1、这j个盘子中有空盘子,这时候i个苹果放入j个盘子的方法和i个苹果放入j-1个盘子的方法是一样的,

得到dp[i][j] = dp[i][j-1] (当满足i<j时,此情况必定成立。)

2、 j个盘子中没有空盘子,那么我们可以从每个盘子中移除一个,那么原问题转换成把i-j个苹果放到j个盘子里。


题目里面很难理解的一点是,为什么没有空盘子时,苹果只拿走一个?

这个问题我们可以这样想,假设放置最少的盘子中有k个苹果,那么这个状态可以唯一地,由连续k次每次从每个盘子中拿走一个苹果而得到,所以就不会出现重复的子状态,也就满足了题目的显示条件!

想清楚以后,还有边界条件需要非常注意,dp[0][i] = 1,dp[1][i] = 1,dp[i][1] = 1;

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

const int MAXN = 15;
int dp[MAXN][MAXN];
int M,N;
// 定义dp[i][j]为把i个苹果放在j个盘子里的放法
//     dp[i][j] = dp[i][j-1] 或者
//     dp[i][j] = dp[i][j-1] +dp[i-j][j]
//
//     如果j个盘子中有空盘子,那么就转换成dp[i][j-1]
//     如果没有空盘子,我们就先给这j个盘子放每个盘子放一个苹果
//     转换成dp[i-j][j]
//
int main()
{
    int T;
    cin>>T;

    while(cin>>M>>N)
    {
        memset(dp,-1,sizeof(dp));
        for(int i = 1; i<=10; i++)
            dp[0][i] = dp[1][i] = dp[i][1] = 1;
        for(int i = 1; i <= 10; i++)
        {
            for (int j =1; j<=10; j++)
            {
                if(dp[i][j] == -1)
                {
                    if (i<j) //证明有空盘子
                        dp[i][j] = dp[i][j-1];
                    else  //证明没有空盘子,那就先给这j个盘子里面每个
                        //都放一个苹果,转换成dp[i-j][j];
                        dp[i][j] = dp[i][j-1] +dp[i-j][j];
                }
            }
        }
        cout<<dp[M][N]<<endl;
    }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值