P4799 [CEOI2015 Day2]世界冰球锦标赛

原题链接

考察:双向dfs

思路:

       爆搜的时间复杂度是O(240).明显TLE.背包的时间复杂度是O(m*n) 也会TLE.所以需要优化.

       这里的优化考虑折半搜索.也就只搜索一半.在搜索另一半的时候进行答案累加.这里先预处理在0~n/2的比赛里选的方案.然后在搜另一半的时候二分找到最大的与当前花费和<=m的左半边下标.这样就优化查找.具体还是看代码吧...

      本蒟蒻自己写的代码T了...O2能过,但还是参考题解不开O2.题解是预处理了两边的方案再累加.

 1 #include <iostream> 
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6 typedef long long LL;
 7 typedef pair<LL,int> PIL;
 8 const int N = 45,M = 1<<23;
 9 LL c[N],m,ans,L[M],R[M];
10 int n,sz;
11 void dfs(int st,LL cost,LL a[],int ed,int& cnt)
12 {
13     if(st>ed)
14     {
15         a[cnt++] = cost;
16         return;
17     }
18     if(c[st]<=m-cost) dfs(st+1,cost+c[st],a,ed,cnt);
19     dfs(st+1,cost,a,ed,cnt);
20 }
21 int main()
22 {
23     scanf("%d%lld",&n,&m);
24     for(int i=0;i<n;i++) scanf("%lld",&c[i]);
25     sort(c,c+n);
26     reverse(c,c+n);
27     int cnt = 0;
28     dfs(0,0,L,n/2,sz);
29     dfs(n/2+1,0,R,n-1,cnt);
30     sort(L,L+sz);
31     for(int i=0;i<cnt;i++)
32     {
33         LL idx = upper_bound(L,L+sz,m-R[i])-L;
34         ans+=idx;
35     }
36     printf("%lld\n",ans);
37     return 0;
38 }

 

 1 #include <iostream> 
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 typedef pair<LL,int> PIL;
 7 const int N = 45,M = 1<<22;
 8 LL c[N],m,ans;
 9 int n,sz;
10 PIL l[M];
11 void dfs_1(int st,int now,LL cost)
12 {
13     l[sz++] = {cost,now};
14     if(cost+c[n/2]>m) return;
15     if(st>n/2) return;
16     if(!(now>>st&1)&&c[st]<=m-cost) dfs_1(st+1,now|(1<<st),cost+c[st]);
17     dfs_1(st+1,now,cost);
18 }
19 void dfs_2(int st,int now,LL cost)
20 {
21     int low = 0,high = sz-1;
22     while(low<high)
23     {
24         int mid = low+high+1>>1;
25         if(l[mid].first<=m-cost) low = mid;
26         else high = mid-1;
27     }
28     if(high>=0) ans+=high+1;
29     for(int i=st;i<n;i++)
30        if(!(now>>st&1)&&c[i]<=m-cost) dfs_2(i+1,now|(1<<i),cost+c[i]);
31 }
32 int main()
33 {
34     scanf("%d%lld",&n,&m);
35     for(int i=0;i<n;i++) scanf("%lld",&c[i]);
36     sort(c,c+n);
37     reverse(c,c+n);
38     dfs_1(0,0,0);
39     sort(l,l+sz);
40     sz = unique(l,l+sz)-l;
41     dfs_2(n/2+1,0,0);
42     printf("%lld\n",ans);
43     return 0;
44 }
吸氧才过的代码

 

posted @ 2021-04-24 12:13  acmloser  阅读(46)  评论(0编辑  收藏  举报