Addition Chains UVA - 529
作者:互联网
考察:迭代加深搜索
思路:
迭代加深适用于预测的答案较小的情况,它比bfs更省空间.这里的加成序列在n<=10000的情况下,长度最长不超过14.因此可以用迭代加深.
光是迭代加深还是会T到爆,所以需要一些剪枝:
1.搜索顺序剪枝:每次优先处理结点少的分支,所以尽可能枚举大的点.所以我们从大到小枚举前面的数字.
2.排除冗余: (1)可以发现a[j]+a[i]与a[i]+a[j]完全相同,所以组合式枚举.
(2)如果a+b == c+d 那么下一步到达的结点相同,搜索了a+b就没必要搜索c+d
3.可行性剪枝(最重要):可以发现如果当前数是s,枚举到第i位.那么最大能扩展到s<<(len-i).如果最大都<n就没必要扩展.
4.迭代加深每次都从1开始,1~i层重复搜.根据上面最大能扩展的数,我们可以从最大>=n的层数开始搜索.
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <set> 5 using namespace std; 6 const int N = 110; 7 int a[N],n,len,logs[N]; 8 bool dfs(int idx)//枚举到第idx个 9 { 10 if(a[idx]==n) 11 { 12 for(int i=1;i<=idx;i++) 13 printf("%d%c",a[i],i==idx?'\n':' '); 14 return 1; 15 } 16 if((a[idx]<<(len-idx))<n) return 0; 17 if(idx>=len) return 0; 18 set<int> s; 19 for(int i=idx;i>=1;i--)//组合枚举 20 { 21 int st = upper_bound(a+1,a+idx+1,a[idx]-a[i])-a; 22 for(int j=i;j>=st;j--) 23 { 24 if(a[j]+a[i]<=a[idx]||s.count(a[j]+a[i])||a[j]+a[i]>n) continue; 25 a[idx+1] = a[j]+a[i]; 26 if(dfs(idx+1)) return 1; 27 s.insert(a[j]+a[i]); 28 } 29 } 30 return 0; 31 } 32 int main() 33 { 34 logs[1] = 1; 35 for(int i=2;i<=14;i++) logs[i] = logs[i-1]*2; 36 while(scanf("%d",&n)!=EOF&&n) 37 { 38 a[1] = 1; 39 len = lower_bound(logs+1,logs+9,n)-logs; 40 while(1) 41 { 42 if(dfs(1)) break; 43 len++; 44 } 45 } 46 return 0; 47 }
标签:迭代,idx,Addition,int,枚举,搜索,UVA,include,Chains 来源: https://www.cnblogs.com/newblg/p/14676363.html