1. 程式人生 > >dfs 放蘋果

dfs 放蘋果

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

程式碼:
 

#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++;return;}
   // if(left==0)return; //去掉沒有用完盤子的情況。
    else if(left==0) ans++;
    else for(int i = min(num, left); i >= (left-1)/(n-cnt)+1; i--)//left>0時
/*

    其中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。

*/
        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;
}

變換:盤子必須用完:
程式碼:
 

#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++;return;}
    if(left==0)return; //去掉沒有用完盤子的情況。
   // 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;
}