第5章回溯法资料.pptVIP

  • 2
  • 0
  • 约9.52千字
  • 约 35页
  • 2017-05-16 发布于湖北
  • 举报
子集和数的问题 假设有n个不同的正整数,找出这些数中所有使其和为正整数m的组合。 Sumofsub() { for(i=1;i=n;i++) x[i]=0; s=0; k=1; x[1]=1; do{ if(s+w[k]==m) 输出解; else if(kn){if(s+w[k]m) s=s+w[k]; else x[k]=0; k=k+1;x[k]=1;} else{ x[n]=0; while(x[k-1]=0 and k1) k=k-1; x[k-1]=0; s=s-w[k-1]; x[k]=1;} } while(k0) if(k=0) 无解; } * 重排原理 对于许多问题而言,在搜索试探时选取x[i]的值顺序是任意的。在其它条件相当的前提下,让可取值最少的x[i]优先。从图中关于同一问题的2棵不同解空间树,可以体会到这种策略的潜力。 图(a)中,从第1层剪去1棵子树,则从所有应当考虑的3元组中一次消去12个3元组。对于图(b),虽然同样从第1层剪去1棵子树,却只从应当考虑的3元组中消去8个3元组。前者的效果明显比后者好。 (a) (b) * 练习 例3:在任意给定的字符表(例如:‘1’,‘2’,‘3’)上,生成一个由该字符组成、含n个字符的序列,但要求生成的序列中没有两个相邻的子序列是相同的。 例如:对于n=5,序列“12321”是问题的一个解,而序列“12323”因有两个相邻的子序列都为“23”,所以该序列不是问题的解。 为找到一个满足要求的长为n个字符的序列,从空序列开始,每次检查当前序列是否含有两个相邻的子序列。在没有两个相邻的子序列相同的情况下,在序列之后添加一个字符,让序列延长。如果当前序列有两个相邻的子序列一样时,就改变序列。如此重复执行延长、检查或修改、检查,直到找到一个满足问题要求的解。 * 练习 算法: {int n,m; int good; char s[MAXLEN]; 输入欲求序列长度n; m=0; good=1; do{ if(good) {延长序列;m++;} else {改变序列;若所有字符都尝试过,则m--} good=检查当前序列是否合理的结果; }while((!good||m!=n)(m!=0)); if(m!=0) 输出解; else 输出无解; } * #include stdio.h #define MAXLEN 100 main() { int n,m; int good; int i,j; char s[MAXLEN]; printf(输入欲求序列的长度n\n); scanf(%d,n); m=0; good=1; do{ if(good) s[m++]=1; else {while(s[m-1]==3) _____?______ ______?_______; } good=1; for(j=0;goodj___?___;j++) { for(i=0;i=j;i++) if(_____?______!=_____?______) break; if(ij) good=0; }}while((!good||m!=n)(m!=0)); if(m!=0) {s[m]=\0; printf(解为%s\n,s);} else printf(无解!\n); } * #include stdio.h #define MAXLEN 100 main() { int n,m; int good; int i,j; char s[MAXLEN]; printf(输入欲求序列的长度n\n); scanf(%d,n); m=0; good=1; do{ if(good) s[m++]=1; else {while(s[m-1]==3) m--; s

文档评论(0)

1亿VIP精品文档

相关文档