Magic Bitwise And Operation HDU - 4016

原题链接

考察:dfs+剪枝

思路:

        很容易想到枚举每一个数,时间复杂度240需要剪枝:

  1. 搜索顺序剪枝:从小到大枚举
  2. 最优性剪枝:如果now&后面所有数>=ans,return &操作只会让数字>=原数.这里不能只与k个数,存在&大数变得更小的情况.
  3. 排除冗余:组合性枚举
  4. 本题的关键剪枝:配合剪枝2,now在不断&的过程中是动态地变小的,因此不需要到nums==k时,再给ans赋值.

感想:

        最优性剪枝是配合极限情况排除当前状态

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 const int N = 45;
 7 const LL INF = 1ll<<61;
 8 int n,k;
 9 LL a[N],ans = INF,pre[N];
10 void dfs(int st,LL now,int nums)
11 {
12     if((now&pre[st])>=ans) return;
13     if(now<ans) ans = now;
14     if(nums==k) return;
15     for(int i=st;i<=n;i++)
16         if((now&a[i])<now) 
17            dfs(i+1,now&a[i],nums+1);
18 }
19 int main() 
20 {
21     int T,kcase = 0;
22     scanf("%d",&T);
23     while(T--)
24     {
25        ans = INF-1;
26        scanf("%d%d",&n,&k);
27        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
28        sort(a+1,a+n+1);
29        LL res = (1ll<<60)-1;
30        pre[n+1] = res;
31        for(int i=n;i>0;i--) pre[i] = pre[i+1]&a[i];
32        dfs(1,res,0);
33        printf("Case #%d: %lld\n",++kcase,ans);
34     }
35     return 0;
36 }

 

posted @ 2021-03-11 16:49  acmloser  阅读(46)  评论(0编辑  收藏  举报