• 网格-递归作业2-放苹果问题


    题目 放苹果问题  
    描述
    把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法(用K表示)?注意:5,1,1和1,5,1是同一种分发。
    
    
    关于输入
    第一行是测试数据的数目t(0<= t <= 20),其后的t行均包含两个整数M和N,以空格分开。
    1<= M <= 25;
    1<= N <= 10;
    
    
    关于输出
    对输入的每组数据M和N,用一行输出相应的K
    
    
    例子输入
    1
    
    7 3
    例子输出
    8
    提示
    采用递归思想解题。

    代码:

     1 //放苹果问题
     2 //2019-11-18
     3 #include<iostream>
     4 using namespace std;
     5 //跟数的划分一个思路,小区别在于允许有空的篮子。可以用搜索或者动规 
     6 int m, n; //把m划分为n份 
     7 int ans; //用于存答案 
     8 void dfs(int step,int x, int left){ //子问题需要用什么参数刻画?划分到第step个数,还剩x +当前数是几
     9     if(step==n-1&&x>=left){ //如果已经划分到倒数第二个数了,并且剩下的数比当前数大,就成为一种分法 
    10         ans++; 
    11     }
    12     else{
    13         for(int i = left; i <= x; i++) //还需要知道当前划分出的数是几,来决定i从几开始循环.i表示分出来的下一个数是啥 
    14             dfs(step+1,x-i,i); 
    15     }
    16 } 
    17 int main(){
    18     int t;
    19     cin>>t;
    20     while(t--){
    21         ans = 0; //注意多组数据输入时的初始化 
    22         cin>>m>>n;
    23         dfs(0,m,0);
    24         cout<<ans<<endl;
    25     } 
    26     return 0;
    27 } 

    备注:

    这道题和https://www.cnblogs.com/fangziyuan/p/5934345.html这道数的划分是类似的。唯一的区别在于是否能有空篮子,但这也不重要,不管是对动规还是搜索。

    对于动规来说,动态转移方程和不能有0就有一点变化:(转+改)

    设f[m][n]为将m分成最多n份的方案数,且其中的方案不重复。
    则有:
    f[m][n] = f[m][n - 1] + f[m - n][n];
               = 1 // m== 0 || n == 1
               = 0 // m < 0
    f[m][n - 1]相当于第一盘子中为0,只用将数分成n - 1份即可。因为0不会大于任何数,相当于f[m][n - 1]中的方案前面加一个为0的盘子,而且不违背f的定义。所以f[m][n - 1]一定是f[m][n]的方案的一部分,即含有0的方案数。
    f[m - n][n]相当于第一个盘子不为0.那么把每个盘子的数-1,方案数是不变的,相当于用n个数去凑m-n

  • 相关阅读:
    模拟测试48
    模拟测试47
    模拟测试46
    NOIP模拟测试29(A)
    NOIP模拟测试19
    NOIP模拟测试18(T3待更新)
    杂题
    noip模拟测试18 T2搜索
    noip模拟测试17 2019-08-11 考后反思
    noip模拟测试14 20190807 考试反思
  • 原文地址:https://www.cnblogs.com/fangziyuan/p/11883123.html
Copyright © 2020-2023  润新知