首页 > 试题广场 >

放苹果

[编程题]放苹果
  • 热度指数:172299 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
\hspace{15pt}我们需要将 m 个相同的苹果放入 n 个相同的盘子中,允许有的盘子空着不放。求解有多少种不同的分法。

输入描述:
\hspace{15pt}输入两个整数 m,n \left(0 \leqq m \leqq 10;\ 1 \leqq n \leqq 10\right) 代表苹果数、盘子数。


输出描述:
\hspace{15pt}输出一个整数,代表不同的分法数量。
示例1

输入

3 2

输出

2

说明

\hspace{15pt}在这个样例中,有 (0,3)(1,2) 这两种不同的分法。
示例2

输入

7 3

输出

8

说明

\hspace{15pt}注意,由于苹果和盘子都是相同的,所以 (5,1,1)(1,5,1) 是同一种分法。
using System;
class test{
    static void Main()
    {
        string input="";
        while((input=Console.ReadLine())!=null)
        {
            string[] str=input.Split(" ");
            int m=int.Parse(str[0]);
            int n=int.Parse(str[1]);
            int result=0;
            result=fenApple(m, n);
            Console.WriteLine(result);
        }
    }
    static int fenApple(int m,int n)
    {
        if(m<0||n<0)
            return 0;
        else if(m==1||n==1)
            return 1;
        else
            return fenApple(m,n-1)+fenApple(m-n, n);
    }
}
发表于 2022-06-25 18:25:47 回复(0)
/*C++动态规划做法*/
//有点像背包问题
//将最终答案看成一个集合,找到这个集合的划分方法
#include <iostream>
using namespace std;
int dp[20][20];
 int main()
 {
     int m,n;

     while(cin>>m>>n)
     {
         for(int i=0;i<=m;i++)
         {
             for(int j=1;j<=n;j++)
             {
                 if(i==0||i==1||j==1)
                     dp[i][j]=1;
                 else if(i>=j) dp[i][j]=dp[i-j][j]+dp[i][j-1];
                 else dp[i][j]=dp[i][j-1];
             }
         }
         cout<<dp[m][n]<<endl;
     }
     return 0;
 }

发表于 2021-07-20 23:06:38 回复(0)
import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            int m = sc.nextInt();
            int n = sc.nextInt();
            
            if(m < 0 || m > 10 || n < 1 || n > 10){
                System.out.println(-1);
            }
            
            //创建二维数组保存状态
            int[][] dp = new int[m+1][n+1];
            for(int i = 0; i <= m; i++){
                dp[i][0] = dp[i][1] = 1;
            }
            
            for(int j = 2; j <= n; j++){
                for(int i = 0; i <= m; i++){
                    if(i < j){
                        dp[i][j] = dp[i][j-1];
                    } else {
                        dp[i][j] = dp[i][j-1] + dp[i-j][j];
                    }
                }
            }
            
            System.out.println(dp[m][n]);
        }
    }
}

发表于 2020-08-16 19:01:34 回复(0)
#include <bits/stdc++.h>
using namespace std;
int func(int m,int n)  
{
    if(m==0||n==1) 
        return 1;    
    if(n>m)
        return func(m,m);
    else
        return func(m,n-1)+func(m-n,n);
}
 
int main(){
    int m, n;
    while (cin >> m >> n){
        cout << func(m, n) << endl;
    }
    return 0;
}

发表于 2020-07-18 14:05:50 回复(0)
import sys

def func1(m,n):
    dp=[[0 for x in range(m+3)] for y in range(n)]
    for i in range(1,m+3):
        dp[0][i]=1
    for i in range(n):
            dp[i][2]=1
    for i in range(1,n):
        for j in range(3,m+3):
            dp[i][j]=dp[i-1][j]+dp[i][j-i-1]
    return dp[-1][-1]

while True:
    a = sys.stdin.readline().strip()
    if a == "":
        break
    a_=a.split(" ")
    m=int(a_[0])
    n=int(a_[1])
    #m<n时,肯定有至少n-m个盘子是空的,对结果不产生影响,应当除去
    if m>=n:
        print(func1(m,n))
    else:
        print(func1(m,m))
动态规划,思路跟递归差不多,不过要注意把空盘子拿掉。
发表于 2020-04-08 17:10:44 回复(0)
#include <bits/stdc++.h>
using namespace std;
int fun(int n,int m)
{
    if(n==0 || m==1) return 1;
    if(n<m) return fun(n,n);
    else return (fun(n,m-1)+fun(n-m,m));
}
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        if(n<0 || n>10 || m<1 || m>10) continue;
        cout<<fun(n,m)<<endl;
    }
    return 0;
}

发表于 2018-08-20 11:55:57 回复(0)
package interview;
import java.util.Scanner;
//n个相同的苹果 放在 m个相同的盘子里
/** f(n,m)
 * 如果没有空盘子f(n-m,m)
 * 如果有空盘子 f(n,m-1)
 * f(n,m)=f(n-m,m)+f(n,m-1)
 */
public class Main{   
   public static int deal(int n,int m){//n苹果 m盘子
       if(n<0)return 0;
       if(n==0||m==1)return 1;
       return deal(n,m-1)+deal(n-m,m);
   }
   public static void main(String args[]){
       Scanner sc=new Scanner(System.in);
       while(sc.hasNext()){
           int n=sc.nextInt();
           int m=sc.nextInt();
           int res=deal(n,m);
           System.out.println(res);
       }
   }
}

发表于 2017-03-21 21:00:43 回复(0)
NWU头像 NWU
/*
放苹果分为两种情况,一种是有盘子为空,一种是每个盘子上都有苹果。
令(m,n)表示将m个苹果放入n个盘子中的摆放方法总数。
1.假设有一个盘子为空,则(m,n)问题转化为将m个苹果放在n-1个盘子上,即求得(m,n-1)即可
2.假设所有盘子都装有苹果,则每个盘子上至少有一个苹果,即最多剩下m-n个苹果,问题转化为将m-n个苹果放到n个盘子上
即求(m-n,n)

综上所述:
(m,n)=(m,n-1)+(m-n,n);
*/

#include <iostream> 
using namespace std; 

int putapples(int m,int n) 
if(m<0)
return 0;
if(m==1||n==1) 
return 1; 
return putapples(m,n-1)+putapples(m-n,n); 

int main() 
int m,n; 
while(cin>>m>>n)
cout<<putapples(m,n)<<endl;
return 0; 
发表于 2016-02-20 16:05:03 回复(35)
枚举:
#include <iostream>

using namespace std;
int main()
{
int appleNum;
int basketNum;
    while(cin >> appleNum >> basketNum){
    
if (appleNum == 0) { cout << 0 << endl;  }
else if (appleNum == 1) { cout << 1 << endl; }
else if (basketNum == 1) { cout << 1 << endl;  }
    
else if (appleNum == 2) { cout << 2 << endl; }
else if (appleNum == 3 && basketNum == 2) { cout << 2 << endl;  }
else if (appleNum == 3 && basketNum > 2) { cout << 3 << endl;  }
else if (appleNum == 4 && basketNum == 2) { cout <<3 << endl;}
else if (appleNum == 4 && basketNum == 3) { cout << 4 << endl;  }
else if (appleNum == 4 && basketNum > 3) { cout << 5 << endl; }
else if (appleNum == 5 && basketNum == 2) { cout << 3 << endl;  }
else if (appleNum == 5 && basketNum == 3) { cout << 5<< endl;  }
else if (appleNum == 5 && basketNum == 4) { cout << 6 << endl;  }
else if (appleNum == 5 && basketNum > 4) { cout << 7 << endl;  }
else if (appleNum == 6 && basketNum == 2) { cout << 4 << endl;  }
else if (appleNum == 6 && basketNum == 3) { cout << 7 << endl;  }
else if (appleNum == 6 && basketNum == 4) { cout << 9 << endl;  }
else if (appleNum == 6 && basketNum == 5) { cout << 10 << endl; }
else if (appleNum == 6 && basketNum > 5) { cout << 11 << endl;  }
else if (appleNum == 7 && basketNum == 2) { cout << 4 << endl;  }
else if (appleNum == 7 && basketNum == 3) { cout << 8 << endl;  }
else if (appleNum == 7 && basketNum == 4) { cout << 11 << endl;  }
else if (appleNum == 7 && basketNum == 5) { cout << 13 << endl;  }
else if (appleNum == 7 && basketNum == 6) { cout << 14 << endl;  }
else if (appleNum == 7 && basketNum > 6) { cout << 15 << endl;  }
else if (appleNum == 8 && basketNum == 2) { cout << 5 << endl;  }
else if (appleNum == 8 && basketNum == 3) { cout << 10 << endl;  }
else if (appleNum == 8 && basketNum == 4) { cout << 15 << endl;  }
else if (appleNum == 8 && basketNum == 5) { cout << 18 << endl;  }
else if (appleNum == 8 && basketNum == 6) { cout << 20 << endl;  }
else if (appleNum == 8 && basketNum == 7) { cout << 21 << endl;  }
else if (appleNum == 8 && basketNum >  7) { cout << 22 << endl;  }
else if (appleNum == 9 && basketNum == 2) { cout <<5 << endl;  }
else if (appleNum == 9 && basketNum == 3) { cout << 12 << endl;  }
else if (appleNum == 9 && basketNum == 4) { cout << 18 << endl;  }
else if (appleNum == 9 && basketNum == 5) { cout << 23 << endl; }
else if (appleNum == 9&& basketNum == 6) { cout << 26 << endl;  }
else if (appleNum == 9 && basketNum == 7) { cout << 28 << endl;  }
else if (appleNum == 9 && basketNum == 8) { cout << 29 << endl; }
else if (appleNum == 9 && basketNum >  8) { cout << 30 << endl;  }
else if (appleNum == 10 && basketNum == 2) { cout << 6 << endl;  }
else if (appleNum == 10 && basketNum == 3) { cout <<13 << endl; }
else if (appleNum == 10 && basketNum == 4) { cout << 20 << endl;  }
else if (appleNum == 10 && basketNum == 5) { cout << 25 << endl;  }
else if (appleNum == 10 && basketNum == 6) { cout << 29 << endl;  }
else if (appleNum == 10 && basketNum == 7) { cout << 32 << endl;  }
else if (appleNum == 10 && basketNum == 8) { cout << 34 << endl; }
else if (appleNum == 10 && basketNum == 9) { cout << 41 << endl;  }
else if (appleNum == 10 && basketNum > 9) { cout << 42 << endl;  }
    }
    return 0;
}
发表于 2016-05-27 22:02:59 回复(92)
#include <iostream>

using namespace std;

/*  解题分析:
        设f(m,n) 为m个苹果,n个盘子的放法数目,则先对n作讨论,
        当n>m:必定有n-m个盘子永远空着,去掉它们对摆放苹果方法数目不产生影响。即if(n>m) f(m,n) = f(m,m)  
        当n<=m:不同的放法可以分成两类:
        1、有至少一个盘子空着,即相当于f(m,n) = f(m,n-1);  
        2、所有盘子都有苹果,相当于可以从每个盘子中拿掉一个苹果,不影响不同放法的数目,即f(m,n) = f(m-n,n).
        而总的放苹果的放法数目等于两者的和,即 f(m,n) =f(m,n-1)+f(m-n,n) 
    递归出口条件说明:
        当n=1时,所有苹果都必须放在一个盘子里,所以返回1;
        当没有苹果可放时,定义为1种放法;
        递归的两条路,第一条n会逐渐减少,终会到达出口n==1; 
        第二条m会逐渐减少,因为n>m时,我们会return f(m,m) 所以终会到达出口m==0.
*/

int func(int m,int n)  //m个苹果放在n个盘子敏感词有几种方法
{
	if(m==0||n==1)  //因为我们总是让m>=n来求解的,所以m-n>=0,所以让m=0时候结束,如果改为m=1,
		return 1;    //则可能出现m-n=0的情况从而不能得到正确解    
	if(n>m)
		return func(m,m);
	else
		return func(m,n-1)+func(m-n,n);
}

int main(){
    int m, n;
    while (cin >> m >> n){
        if (m < 0 || m > 10 || n < 0 || n > 10) continue;
        cout << func(m, n) << endl;
    }
    return 0;
}


发表于 2016-09-11 11:25:56 回复(18)

"""函数递归思想,主要表达抽象思维,计算机语言魅力在于,给定了计算路径或者规则,输入和输出就交给晶体管解决了。言归正传哈,不妨设 f(m,n) 为分法总数,接下来就是要给定计算路径了,注意这里的计算路径类似数列递推公式,给出首几项的值,求第n项递推公式,但是计算机不要求具体的计算公式,因为计算机它可以自行迭代啊!故最简单的方法,就是通过找出第n项的前几项式子,看看它们和通项式子的关系式(也就是可迭代路径),观察规律如下:

双变量,显然,m, n 都递归,先考虑初始项,m =0, n=1 (题目条件),无论是无苹果还是一个盘子,都只有一种放法,即 f(0,n) = f(m ,1) =1. (注意 f(0,1) 只是特殊条件
先看变量n(较简单),不妨设 m < n, 盘多果少,此时,可用盘子为m,由于盘子一致,所以,f(n,m) =f(m,m).
再看m变量递归, 不妨设m >=n, 即确保盘子不空着,设每个盘子至少一个苹果,则放法数为f(m-n,n)。注意,f(m,n)= f(不空盘子法子)+f(空盘子法子),f(不空盘子法子)=f(先每个盘子放一个* 剩下苹果再放)= 1 * f(m-n,n) ,简单解释下f(不空)怎么来的,事件状态A = 状态(A1 + A2),熵增量(A) = 熵增量(A1 * A2) 
最后看f(空盘子),比上面好理解,即至少存在一个空盘子,则f(空)=f(m,n-1) 。推到完毕,以下是py。
"""
def f(mn):
    if m == 0 or n == 1:
        return 1
    if m < n:
        return f(m, m)  
    else:
        return (f(m, n-1) + f(m-n, n))
while True:
    try:
        m, n = map(int,input().split())
        print(f(m,n))
    except:
        break
#最后,各位观众老爷们,动态规划做成了数字游戏推到,创造不易,请点赞支持,谢谢了!
发表于 2024-07-02 03:38:16 回复(2)
递推的方式,利用公式f(m, n)=f(m, n-1)+f(m-n, n)来填表。

将m个苹果放入n个盘子里,包含了2个事件:至少有一个盘子空着的事件A,和所有盘子都不空的事件B(每个盘子都至少有一个苹果)。A∪B即所有情况。A就是求f(m, n-1),B就是f(m-n, n)。事件B表示每个盘子都有一个苹果时再放m-n个苹果,等价于每个盘子都没有苹果时放m-n个苹果,所以可以直接写成 f(m-n, n)。注意m-n可能为负数,此时要返回0。

例如,f(4,4)=f(4,3)+f(0,4),f(0,4)等于1,表示在4个盘子中各放1个苹果

while True:
    try:
        m, n = map(int, input().split())
    except:
        break
    else:
        a = [[0 for i in range(n+1)] for j in range(m+1)]
        for i in range(m+1):
            for j in range(1,n+1):
                if i == 0 or i== 1 or j == 1:
                    a[i][j] = 1
                elif i-j >= 0:
                    a[i][j] = a[i][j-1] + a[i-j][j]
                else:
                    a[i][j] = a[i][j-1]
        print(a[m][n])

发表于 2021-08-21 14:56:30 回复(0)
/*其实这题考的是数学啊,首先当有0个苹果或者是1个盘子的时候,只有一种分法,而其他情况
可以分为两种情况讨论:
   1、m<n,则至少有n-m个盘子是空的,此时就相当于将m个苹果分到m个盘子中,此时(m,n)=(m,m)
   2、m > n,分法是两种情况分法的和,有一个空盘子和没有空盘子,即(m,n) = (m,n-1)+(m-n,n)
*/
def putApple(m,n):
    if m == 0 or n == 1:
        return 1
    if n > m:
        return putApple(m,m)
    else:
        return putApple(m,n-1) + putApple(m-n,n)
        
        
while True:
    try:
        n, m = map(int,input().split())
        print(putApple(n, m))
    except:
        break

发表于 2018-08-31 22:57:47 回复(6)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main() {
	int M, N;
	while (cin >> M >> N) {
		if (M < 1 || M>10 || N < 1 || N>10) {
			cout << -1 << endl;
			continue;
		}
		vector<vector<int>> dp(M + 1, vector<int>(N + 1, 0));
		for (int i = 1; i <= N; i++) dp[0][i] = 1;
		for (int i = 1; i <= M; i++)
			for (int j = 1; j <= N; j++)
				dp[i][j] = dp[i][j - 1] + (i < j ? 0 : dp[i - j][j]);
		cout << dp[M][N] << endl;
	}
}

发表于 2017-03-17 22:43:56 回复(4)
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            int m = sc.nextInt();
            int n = sc.nextInt();
            if(m<1 || n>10){
                System.out.println(-1);
            }else{
                System.out.println(shareCount(m,n));
            }
            
        }
    }
    public static int shareCount(int m, int n){
        if(m<0){
            return 0;
        }
        if(m==1 || n==1){
            return 1;
        }
        return shareCount(m, n-1)+shareCount(m-n,n);
    }
}

发表于 2016-09-02 21:05:45 回复(2)
#include <stdio.h>
#include <stdlib.h>
int func(int m,int n)
{
    if(n<0||m<0)
    {
        return 0;
    }
    else if(m==1||n==1)
    {
        return 1;
    }
    else
    {
        return func(m,n-1)+func(m-n,n);
    }
}

int main()
{
    int m,n;
    while(scanf("%d %d",&m,&n)!=EOF)
    {
        printf("%d\n",func(m,n));
    }
    return 0;
}


发表于 2021-07-16 12:02:51 回复(1)
#  解题分析:
#        设f(m,n) 为m个苹果,n个盘子的放法数目,则先对n作讨论,
#        当n>m:必定有n-m个盘子永远空着,去掉它们对摆放苹果方法数目不产生影响。即if(n>m) f(m,n) = f(m,m)
#        当n<=m:不同的放法可以分成两类:
#        1、有至少一个盘子空着,即相当于f(m,n) = f(m,n-1);
#        2、所有盘子都有苹果,相当于可以从每个盘子中拿掉一个苹果,不影响不同放法的数目,即f(m,n) = f(m-n,n).
#        而总的放苹果的放法数目等于两者的和,即 f(m,n) =f(m,n-1)+f(m-n,n)
#    递归出口条件说明:
#        当n=1时,所有苹果都必须放在一个盘子里,所以返回1;
#        当没有苹果可放时,定义为1种放法;
#        递归的两条路,第一条n会逐渐减少,终会到达出口n==1;
#        第二条m会逐渐减少,因为n>m时,我们会return f(m,m) 所以终会到达出口m==0.
#

def putApple(m,n):
    if m==0 or n==1:
        return 1
    elif n>m:
        return putApple(m, m)
    else:
         return putApple(m, n-1)+ putApple(m-n, n)
         
while True:
    try:
        n, m = map(int,input().split())
        print(putApple(n, m))
    except:
        break
发表于 2020-07-14 08:55:17 回复(0)
递归思想:f(m,n)可以分成两种情况:
1.有一个盘子是空的(这里为什么要说是一个盘子而不是至少一个呢?因为至少一个已经包含在内了,递归实现),此时为f(m,n-1);
2.没有空盘子,此时每个盘子至少有一个苹果,则为f(m-n,n);
已知条件:
1.苹果数量小于0放置方式为0;
2.苹果数量为0/1或者盘子数量为1时放置方式为1;(之前我也是觉得m=0时应该是为0,后来想了想,如果是m(2,2)的话结果应该为2,而m(2,2)=m(2,1)+m(0,2),前者值为1,后者如果为0的话就不正确了,所以当m为0的时候应该是为1的)
3.其余情况使用递归
import java.util.Scanner;

public class Main{
	
	public static void main(String[] args){
		Scanner in = new Scanner(System.in);
        while(in.hasNext()){
            int m = in.nextInt();
            int n = in.nextInt();
            System.out.println(count(m,n));
        }
        in.close();
	}
	
	public static int count(int m,int n){
		
		if(m<0)
			return 0;
		if(m == 0 || n == 1)
			return 1;
		return count(m,n-1)+count(m-n,n);
	}
} 
对了,这里还要注意一下,测试用例不止一条,有多条,所以一定要使用in.hasNext()进行while循环,否则结果报错,郁闷得很,使用BufferedReader不知道如何无限输入,如果使用while(true)就跳不出了
发表于 2017-09-14 11:10:19 回复(3)
/*应用动态规划*/
import java.util.Scanner;

public class Main{
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
			int num_apple = sc.nextInt();
			int num_panzi = sc.nextInt();
			calculate(num_apple,num_panzi);

		}
	}
	public static void calculate(int a,int b){
		int[][] count = new int[a+1][b+1];
		for(int i=0;i<=a;i++){
			count[i][1]=1;
			count[i][0]=1;
		}
		for(int j=0;j<=b;j++){
			count[1][j]=1;
			count[0][j]=1;
		}
		for(int i=2;i<=a;i++){
			for(int j=2;j<=b;j++){
				if(i>=j){
					count[i][j] = count[i-j][j]+count[i][j-1];
				}else{
					count[i][j]=count[i][j-1];
				}

			}
		}
		System.out.println(count[a][b]);
	}

}


发表于 2017-04-03 21:02:29 回复(1)

法1:采用递归做法
其实这根将一个整数m分成n个整数之和是类似的。

设f[m][n]为将m分成最多n份的方案数,且其中的方案不重复,即每个方案前一个份的值一定不会比后面的大,序列是一个不降序列
当m>=n时f[m][n] = f[m][n - 1] + f[m - n][n]
f[m][n - 1]相当于第一盘子中为0,有空盘子,只用将数分成n - 1份即可。因为0不会大于任何数,相当于f[m][n - 1]中的方案前面加一个为0的盘子。
f[m - n][n]相当于在每个盘子中加一个数1,没有空盘子。因为每个盘子中加一个数1不会影响f[m][n - 1]中的方案的可行性,也不会影响f的定义。所以f[m - n][n]一定是f[m][n]的方案的一部分,即不含有0的方案数。

当m<n的时候,肯定最少有n-m个空盘子,不过幸好,这些空盘子并不影响最后的结果,因为每种方法都带有着些空盘子,剩下的问题就是把m个苹果放到m个盘子有多少种方法了。f[m][n]=f[m][m)] m<n

临界条件,递归出口要定义好
n=1时,所有苹果都放在同一个盘子里 f(m,n)=1
m<=1时,没有苹果,f(m,n)=1

public int fun(int m,int n){
    if(m<=1 || n==1){
        return 1;
    }else if(m<n){
        return fun(m,m);
    }else{
        return fun(m,n-1)+fun(m-n,n);
    }
}

法2:动态规划
当数据规模较大时,递归的方式效率很低。使用动态规划,个人认为重点在于找对状态转移方程。
f[m][n] = f[m][n - 1] + f[m - n][n];
= 1 // m<= 1 || n <= 1

public int fun(int m,int n){
    int[][] arr = new int[m+1][n+1];
    for(int i = 0; i <= m; i++){
        for(int j = 0;j<=n;j++){
            if(i<=1 || j==1){
                arr[i][j] = 1;
            }else if(i<j){
                arr[i][j] = arr[i][i];
            }else{
                arr[i][j] = arr[i][j-1]+arr[i-j][j];
            }
        }
    }
    return arr[m][n];
}
编辑于 2021-01-26 13:22:56 回复(2)