POJ 1664 放苹果

题目链接~~>

                    这题开始用搜索过了,但是看别人代码用递归而且比搜索时间短,还可以用dp和母函数做。

方法一:

              递归思想:

                (1):当盘子数为1的时候,只有一种放法就是把所有苹果放到一个盘子里。
       (2):当苹果数为1的时候,也只有一种放法,注意题目中说明,盘子之间并无顺序,所以不管这个苹果放在哪个盘子里,结果都算一个。
       (3):当m<n时,因为此时最多只能放到m个盘子中去(一个里放一个),实际上就相当于把m个苹果放到m个盘子里一样,也就是f(m,m);
       (4):当m==n时,此时分两种情况讨论,一种是一个盘子里放一个,只是一种,第二种是,至少有一个盘子里不放苹果这就相当于是f(m,m-1);
       (5):当m>n时,也分两种情况讨论,一种是至少有一个盘子里不放苹果,这样子就相当于f(m,n-1),第二种是,先取出n个苹果一个盘子里放一个,再将剩下的m-n个苹果放到n个盘子里去,即f(m-n,n);
综上所述:
得到递归表达式:
                              f(m,n)=1 当 m=1或n=1;
                              f(m,n)=f(m,m) 当m<n;
                              f(m,n)=1+f(m,m-1) 当m=n;
                              f(m,n)=f(m-n,n)+f(m,n-1);

 

递推代码:

#include<stdio.h>
int f(int m,int n)
{
    if(m==1||n==1)//当只有一个苹果或一个盘子时就剩下一种办法
                 return 1;
    if(m<n)      //如果盘子多,苹果少,按苹果数进行分配
                 return  f(m,m);
    else if(m>n) //当苹果大于盘子的时候,按空一个盘和每个盘子都放一个开始递归
                 return f(m,n-1)+f(m-n,n);
    else        //当盘子数和苹果个数一样多时,每个盘子放一个是一种,加上空一个盘子
                 return 1+f(m,n-1);
}
int main()
{
    int t,m,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&m,&n);
        printf("%d\n",f(m,n));
    }
    return 0 ;
}

方法二:

           DP思想:先不考虑空盘子的情况,因为加上一个空盘子和加上多个空盘子是一样的结果。先考虑每个盘子都有苹果的情况。例如:五个苹果放进两个盘子里。1.可以每个盘子里先放一个苹果,那就相当于三个苹果放进两个盘子里;2.可以让先将其中一个盘子里放一个,再将剩下的放进剩余的盘子里。最后五个苹果放进二个盘子了就相当于五个苹果放进一个盘子里的情况(给它加上一个空盘子,就相当于两个盘子)加上五个苹果放进两个盘子。

          方程:a[ i ][ j ] = a[ i-1 ][ j-1 ]+a[ i-j ][ j ] ;

代码:

#include<stdio.h>
#include<string.h>
int main()
{
    int T, n, m, i, j, ans, a[15][15];
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(a,0,sizeof(a));
        a[1][1] = 1;
        for(i = 2; i<=n; i++)
        for(j = 1; j<=i; j++)
            a[i][j] = a[i-1][j-1]+a[i-j][j];
        ans = 0;
        for(i = m; i > 0; i--)
            ans+=a[n][i];
        printf("%d\n",ans);
    }
    return 0;
}
        




 



 

 

你可能感兴趣的:(POJ 1664 放苹果)