Magic Bitwise And Operation HDU - 4016
考察:dfs+剪枝
思路:
很容易想到枚举每一个数,时间复杂度240需要剪枝:
- 搜索顺序剪枝:从小到大枚举
- 最优性剪枝:如果now&后面所有数>=ans,return &操作只会让数字>=原数.这里不能只与k个数,存在&大数变得更小的情况.
- 排除冗余:组合性枚举
- 本题的关键剪枝:配合剪枝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 }