【dfs】p1025 数的划分
作者:互联网
P1025 数的划分
题目描述
将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序)。
例如:n=7,k=3,下面三种分法被认为是相同的。
1,1,5; 1,5,1; 5,1,1;
问有多少种不同的分法。
输入输出格式
输入格式:
n,k (6<n<=200,2<=k<=6)
输出格式:
一个整数,即不同的分法。
输入输出样例
输入样例#1:输出样例#1:7 3
4
说明
四种分法为:1,1,5;1,2,4;1,3,3;2,2,3;
noip2001年提高组第二题
思路:
一.dfs:直接跑dfs
不剪枝的版本:
#include"bits/stdc++.h" using namespace std; int a[11111]= {1},n,k,tot=0; inline void dfs(int s,int t) { //s是拆分的数,t是拆分了几个数 if(t>k) return;//如果t比拆分的长度大,直接跳出。 for(int i=a[t-1]; i<=s; i++) //进行拆分。 if(i<n) { a[t]=i;//保存拆分的数 s-=i;//减去拆分的数 if(s==0&&t==k) tot++;//如果拆分完成并且符合长度时,total就加一 else dfs(s,t+1); s+=i;//进行回溯 } } int main() { cin>>n>>k; dfs(n,1); cout<<tot; return 0; } //感谢lyq大佬提供代码 @lyq您真是吊打我
额....838ms,这也太慢了吧!
你们这是什么dfs啊!你们害人不浅啊!
剪枝版本:
原理:
1.按分解的数递增排列
2.上限为a[i]<=m/(k-i+1)
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<vector> #include<map> #include<string> #include<cstring> using namespace std; const int maxn=999999999; const int minn=-999999999; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int n,k,a[22000],ans,m; void dfs(int k) { if(n==0) return; if(k==m) { if(n>=a[k-1]) { ans++; } 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() { cin>>n>>m; a[0]=1;//设置初始化条件 dfs(1);//进行搜索 cout<<ans; return 0; }
优化不少吧!我会在下一篇文章里写一下剪枝(原谅我太垃圾了)
二.递推
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<vector> #include<map> #include<string> #include<cstring> using namespace std; const int maxn=999999999; const int minn=-999999999; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int dt(int n, int k) { if(n < k) return 0; //如果n<k 肯定不可能每个盒子都有 if(n == k) return 1; //盒子和小球数相等 每个盒子里一个小球 if(k == 1) return 1; //盒子只有一个时候 把剩下小球都放进去 return dt(n-1, k-1) + dt(n-k, k); } int main() { int n=read(), k=read(); printf("%d", dt(n, k)); return 0; } //递推做法
其实和放小球的题一样了....
速度和剪枝差不多,不过好想多了,嘻嘻嘻嘻(可能是我太菜了)
二.dp
和递推差不多就不写了
标签:剪枝,const,int,dfs,p1025,划分,999999999,include 来源: https://www.cnblogs.com/pyyyyyy/p/10721998.html