题目:http://ybt.ssoier.cn:8088/problem_show.php?pid=1440
题目简述:将n划分成k份,问有多少种不同的分法
思路:深搜剪枝
一个个找再对比时间一定会超
何不想一下,既然要不同的分法(顺序无用),那就给他规定一个顺序,比如递增,那样就可以不考虑重复;
那么,按照递增来就可以开始剪枝了
1:下界
由于是递增序列,所以下界就是这一组数列的上一个数,即a[s-1];
2:上界
为保证递增序列,即之后的每个数都比上一个数值大,那么后面的每个数都不可能超过余下数字的平均值
所以上界就是余下的数字除以剩余的划分步骤,即m/(k-s+1)
上代码
#include<bits/stdc++.h>
using namespace std;
int n,k,a[201],ans=0;
void dfs(int m,int s){//搜索
if(s==k){//步数已经达到了
if(m>=a[s-1]){//达成递增效果,也就是这个方案可行且没有重复
ans++;//划分数+1
}
return;//再见
}
int i;
for(i=a[s-1];i<=m/(k-s+1);++i){//上下界剪枝
a[s]=i;
m-=i;
dfs(m,s+1);
m+=i;//记得回溯
}
}
int main(){
scanf("%d%d",&n,&k);
a[0]=1;
dfs(n,1);//开搜
printf("%d",ans);
return 0;
}
题目总结:本次运用到了“上下界剪枝”这一知识点
合理运用剪枝,保证时间不爆,是这道题的亮点,也是难点