双向dfs可以把2^n的复杂度变为(1+x)*2^(n/2)(我不太确定x是多少,我认为应该是n/2,但是貌似其他人不是这么说的)
思路:把需要枚举的值拆成两半,第一遍dfs处理出前一半中所有的可能情况记录在一个数组里,排序、去重,第二遍dfs搜索后一半每得到一个部分解就到数组中寻找相应的最优的另一个部分解(二分),更新答案即可。
这道题的代码:
1 int f[(int)1e7]; 2 ll g[50]; 3 ll n,w,m,ans,cnt; 4 5 void dfs1(int x,int sum){ 6 f[++cnt] = sum; 7 while(x <= m)if(sum+g[x] <= w)break;else x++; 8 if(x > m)return; 9 while(x <= m){ 10 dfs1(x+1,sum+g[x]); 11 x++; 12 } 13 } 14 15 void dfs2(int x,int sum){ 16 ans = max(ans,1ll*sum+(*(ub(f+1,f+cnt+1,w-sum)-1))); 17 while(x <= n)if(sum+g[x] <= w)break;else x++; 18 if(x > n)return; 19 while(x <= n){ 20 dfs2(x+1,sum+g[x]); 21 x++; 22 } 23 } 24 25 int main(){ 26 w = read(),n = read();m = n>>1; 27 rep(i,1,n)g[i] = read(); 28 sort(g+1,g+n+1);reverse(g+1,g+n+1); 29 dfs1(1,0); 30 sort(f+1,f+cnt+1);cnt = unique(f+1,f+cnt+1)-f-1; 31 dfs2(m+1,0); 32 cout << ans; 33 return 0; 34 }
ps:双向dfs的板子貌似确实挺简单的