题意:n个数字取出k个数字进行“与”操作,求最少的结果。
思路:首先明白“与”操作的结果,显然应先将数字排列,小的先取必然最优。下面dfs+剪枝即可,
剪枝:
1. dfs路径上不断更新ans,不用等搜到底,“与“”操作只会越来越小;
2. 与后缀“与”如果没有ans小就剪枝;
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
LL a[45], sum[45], ans;
int vis[45], n, k;
void dfs(int index, int cnt, LL res){
if(res < ans) ans = res;//剪枝1
if(index == n || cnt == k) return;
if((res & sum[index]) >= ans) return;//剪枝2
dfs(index + 1, cnt + 1, res & a[index]);//选择
dfs(index + 1, cnt, res);//不选择
}
int main(){
int T;
scanf("%d", &T);
for(int cas = 1; cas <= T; cas++){
scanf("%d%d", &n, &k);
for(int i = 0; i < n; i++) scanf("%lld", &a[i]);
sort(a, a + n);
sum[n - 1] = a[n - 1];
for(int i = n - 2; i >= 0; i--) sum[i] = sum[i + 1] & a[i];
ans = INF;
dfs(0, 0, (1LL << 61) - 1);
printf("Case #%d: %lld\n", cas, ans);
}
return 0;
}