P1025 [NOIP2001 提高组] 数的划分
作者:互联网
啊啦啦,时隔许久,我终于又开始了我的AC之路,毕竟再不写写代码我就废了,洛谷yyds
----------------------(分割线)-------------------------
题目
将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序)。
例如:n=7,k=3,下面三种分法被认为是相同的。
1,1,5;
1,5,1;
5,1,1.
问有多少种不同的分法。
思路
这道题其实我看好多人是用动态规划做的,当然莫得问题,不过对于像我这样的小辣鸡来讲,动态规划还是有点让人头疼的
所以,我们采用另一种方式,dfs,我觉得这里也可以说是递归,一样的啦!
其实一说dfs,我们就会想到树,没错,这道题确实可以这么想,第一层第二层第三层那样子…
所以大概就是这个样子:我们先选第一个数字,他可以选的范围是从1开始到某个数(这个等下讲,很重要),确定它之后,我们在第一个数字的基础上再去选择第二个数字,这样一直向下搜索,直到找到个数满足同时数字和也满足时,结果加一。
这样其实就是不断的调用调用…所以我们关键要把dfs这个函数写出来,然后一直调用就好了
那这个函数的话,也很清晰,就是 满足条件就跳出,结果数加一,不满足的话,遍历当前可选,然后分别dfs,关键就是在于这个当前可选
我们要考虑当前可选的值有哪些
因为不可以重复,所以我们给的办法就是后一个数字一定要大于等于前一个,这样才可以保证不重复,那么,当前可选的初值也就是前一个数字的取值,那截止条件是什么呢?就是当前可选最大是多少呢?
假设前面已经取定num个数字,一共需要k个,那还差k-num个数字,当前数字若取a的话,后面的数一定大于等于a,即 sum+a(k-num)<=n,sum为已取数的和,这个需要自己想一想,很重要!sum+a(k-num)这种情况是后面所有的数都取a,但是这是最小的情况,后面的数还可以取大于a的,我们要的是总的sum等于n,所以这种最小情况只能是小于等于n。
好了,有点啰嗦,也不知道讲清楚了没有
还是看代码吧
代码
#include <iostream>
using namespace std;
int ans=0;//结果数
int n,k;
void dfs(int now,int sum,int num)
{
if(num==k)
{
if(sum==n)
{
ans++;
}
return;
}
for(int i=now;sum+i*(k-num)<=n;i++)
{
dfs(i,sum+i,num+1);
}
}
int main()
{
cin>>n>>k;
dfs(1,0,0);
cout<<ans<<endl;
return 0;
}
标签:NOIP2001,int,sum,dfs,P1025,划分,num,当前,数字 来源: https://blog.csdn.net/qq_51052824/article/details/117634210