【bzoj4800】: [Ceoi2015]Ice Hockey World Championship
N<=40所以如果直接dfs背包会TLE
考虑Meet-in-the-middle
如果把N个物品分成前后A B两段分别背包
分别在A B中可行的方案的花费记录在a b中
答案就是a[i]+b[j]<=M的个数
把a b排序 然后序列就是单调的了
两个指针扫一遍就好了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <cstdio> 6 #include <algorithm> 7 using namespace std; 8 #define ll long long 9 10 11 ll n,m,mid,ans; 12 ll c[50],a[2][1100000],ca[2]; 13 14 void dfs(int p,int x,ll cost){ 15 if (cost>m) return; 16 if ((x>=mid && p==0) || (x>=n && p==1)){ 17 a[p][++ca[p]]=cost; 18 return; 19 } 20 dfs(p,x+1,cost+c[x+1]); 21 dfs(p,x+1,cost); 22 } 23 24 int main(){ 25 scanf("%lld%lld",&n,&m); 26 for (int i=1;i<=n;i++) scanf("%lld",&c[i]); 27 mid=n/2; 28 dfs(0,0,0); 29 dfs(1,mid,0); 30 sort(a[0]+1,a[0]+ca[0]+1); 31 sort(a[1]+1,a[1]+ca[1]+1); 32 for (int l=1,r=ca[1];l<=ca[0] && r>=1;ans+=r,l++) while (a[0][l]+a[1][r]>m) r--; 33 printf("%lld\n",ans); 34 return 0; 35 }
竟然有Rank4(2017.3.31)。。好快啊。。