第5章节 搜索跟回溯算法(c++版)资料.pptVIP

  • 1
  • 0
  • 约1.73万字
  • 约 45页
  • 2019-12-31 发布于湖北
  • 举报
第五章 搜索与回溯算法 【例9】数的划分(NOIP2001) 【问题描述】 将整数n分成k份,且每份不能为空,任意两种分法不能相同(不考虑顺序)。例如:n=7,k=3,下面三种分法被认为是相同的。 1,1,5; 1,5,1; 5,1,1; 问有多少种不同的分法。 【输入格式】 n,k (6n≤200,2≤k≤6) 【输出格式】 一个整数,即不同的分法。 【输入样例】 7 3 【输出样例】 4 { 4种分法为:1,1,5;1,2,4;1,3,3; 2,2,3 说明部分不必输出 } 【算法分析】 方法1、回溯法,超时,参考程序如下。 #includecstdio #includeiostream #includecstdlib using namespace std; int n,i,j,k,rest,sum,total; int s[7]; int main() { cout Input n k; cin n k; total = 0; s[1] = 0; i = 1; while (i) { s[i]++; if (s[i] n) i--; else if (i == k) { sum = 0; for (j = 1; j = k; j++) sum += s[j]; if (n == sum) total++; } else { rest -= s[i]; i++; s[i] = s[i-1] - 1; } } cout total; system(pause); return 0; } 方法2、递归,参考程序如下。 #includecstdio #includeiostream #includecstdlib using namespace std; int n,k; int f(int a,int b,int c) { int g = 0,i; if (b == 1) g = 1; else for (i = c; i = a/b; i++) g += f(a-i,b-1,i); return g; } int main() { cout Input n,k:; cin n k; cout f(n,k,1); system(pause); return 0; } 方法3、用动态循环穷举所有不同的分解,要注意剪枝,参考程序如下。 #includecstdio #includeiostream #includecstdlib using namespace std; int n,k,total; int min(int x,int y) { if (x y) return x; else return y; } void select(int dep,int rest,int last) { int i; if (dep == 0) total++; else for (i = min(rest-dep+1,last); i = rest/dep; i--) select(dep-1,rest-i,i); } int main() { cout Input n,k:; cin n k; total = 0; select(k,n,n); cout total; system(pause); return 0; } 方法4、递推法 首先将正整数n分解成k个正整数之和的不同分解方案总数等于将正整数n-k分解成任意个不大于k的正整数之和的不同分解方案总数(可用ferror图证明之),后者的递推公式不难得到,参考程序如下。 #includecstdio #includeiostream #includecstdlib #i

文档评论(0)

1亿VIP精品文档

相关文档