【來源】
NOIP-2001
一本通題庫-1440
LibreOJ-10018
HRBUST-1216
vjudge
注意:HRBUST和其他OJ的題目題意相同,但有多組數據。
本文題面以LibreOJ爲準,代碼通用。
【題目描述】
將整數 n 分成 k 份,且每份不能爲空,問有多少種不同的分法。當 n=7,k=3 時,下面三種分法被認爲是相同的:1,1,5; 1,5,1; 5,1,1
【輸入格式】
一行兩個數 n , k。
【輸出格式】
一行一個整數,即不同的分法數。
【樣例輸入】
7 3
【樣例輸出】
4
【樣例解釋】
四種分法爲:1,1,5;1,2,4;1,3,3;2,2,3。
【數據範圍】
。
【解析1】
深搜剪枝。
求n無序劃分成k份的方案數。
在搜索中依次枚舉,然後判斷。
同時控制好節點的上界和下界,這樣就是剪枝。
【代碼1】
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define RI register int
#define re(i,a,b) for(RI i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
const int N=205;
const int inf=1e9;
int n,m,ans;
int a[10];
void dfs(int x,int y,int z) {
if(y==1 && x>=z) {
ans++;
return;
}
for(int i=(z ? z : 1); i<=x; i++)
dfs(x-i,y-1,i);
}
int main() {
while(scanf("%d%d",&n,&m)!=EOF) {
ans=0;
dfs(n,m,0);
printf("%d\n",ans);
}
return 0;
}
【解析2】
動態規劃。
顯然,
- 當i=j時,1
- 當i<j時,0
- 當i>j時,分爲兩種情況
- 有1的:方案數爲
- 沒有1的:方案數爲
所以,狀態轉移方程爲:、
【代碼2】
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define RI register int
#define re(i,a,b) for(RI i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
const int N=205;
const int inf=1e9;
int n,k;
int f[N][10];
int main() {
while(scanf("%d%d",&n,&k)!=EOF) {
for(int i=0; i<=n; i++) for(int j=0; j<=MIN(i,k); j++) {
if(j<2) {
f[i][j]=1;
continue;
}
f[i][j]=f[i-1][j-1];
if(i>=j) f[i][j]+=f[i-j][j];
}
printf("%d\n",f[n][k]);
}
return 0;
}