1440:【例題1】數的劃分
時間限制: 1000 ms 內存限制: 65536 KB
提交數: 1543 通過數: 1026
【題目描述】
將整數n分成k份,且每份不能爲空,任意兩份不能相同(不考慮順序)。
例如:n=7,k=3,下面三種分法被認爲是相同的。
{1,1,5};{1,5,1};{5,1,1};
問有多少種不同的分法。 輸出一個整數,即不同的分法。
【輸入】
兩個整數n,k(6<n≤200,2≤k≤6),中間用單個空格隔開。
【輸出】
一個整數,即不同的分法。
【輸入樣例】
7 3
【輸出樣例】
4
【提示】
四種分法爲:{1,1,5};{1,2,4};{1,3,3};{2,2,3}。
思路:將數字 n 劃分成 k 份,就是求 x1+x2+…+xk=n 方程的解,依次枚舉 x1到xk 的值,然後判斷。
剪枝分析
由於分解數不考慮順序,因此設定分解數依次遞增,所以擴展結點時的下個數應是不小於前一個擴展結點的值,即 a[i−1]≤a[i]
假設我們將 n 已經分解成了 a[1]+a[2]+…+a[i−1],則 a[i] 的最大值爲將 i~k 這 k-i+1 份平均劃分,即設 m=n−(a[1]+a[2]+…+a[i−1]),則 a[i]≤m/(k−i+1),所以擴展結點的上個數是 m/k−i+1.
#include<cstdio>
#include<iostream>
using namespace std;
int m,n,k,s;
int a[10];
void dfs(int k){
if(n == 0) return;
if(k == m)
{
if(n >= a[k-1])
{
s++;
return;
}
}
for(int i = a[k-1]; i <= n/(m-k+1);i++)//剪枝
{
a[k] = i;
n -= i;
dfs(k+1);
n += i;
}
}
int main(){
scanf("%d%d",&n,&m);
a[0] = 1;
dfs(1);
printf("%d",s);
return 0;
}