HDU 4016 Magic Bitwise And Operation(dfs+剪枝)

来源:互联网 发布:山海经知乎 编辑:程序博客网 时间:2024/04/30 16:31

Magic Bitwise And Operation

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 1535    Accepted Submission(s): 600


Problem Description
Given n integers, your task is to pick k out of them so that the picked number are minimum when do bitwise “AND” among all of them.
For example, there are three integers 5, 6 and 7. You are asked to pick two of them. Your possible strategy is (5, 6), (5, 7) or (6, 7). The values when do bitwise and all the picked numbers together are as follows:
5 and 6 = 4
5 and 7 = 5
6 and 7 = 6
The smallest one is 4.
 

Input
There are multiple test cases for this problem. The first line of the input contains an integer denoting the number of test cases.
  For each test case, there are two integers in the first line: n and k, denoting the number of given integers and the number of integers you are asked to pick out. n <= 40
  The second line contains the n integers. You may assume that all integers are small than 2^60.

Notes: There are about one thousand randomly generated test cases. Fortunately 90% of them are relatively small.
 

Output
For each test case, output only one integer is the smallest possible value.
 

Sample Input
33 25 6 78 2238 153 223 247 111 252 253 24740 101143632830316675007 558164877202423550 1152356080752164603 1143911006781551605 11326550055017512631152919305583327167 1141662230660382702 862439259920596463 1151777428397603327 1008771132016295871855666336963428351 1151795583225167807 1152634943314572791 1071856693060561407 11326508728034263031124211056982081471 1152917106425982911 1152815392070041535 1080863910568853481 2882303718563509751080720560532488126 864686455262281727 576460673919991167 574191342855241589 11522337600501186511152921504605798263 1152912708241186815 1079738008506187487 1075796261476483027 10808544788207308791152885219917823999 1151725162940854259 1147529498501577715 571956602920235519 11345456306436162481152921218991521790 1152921496000052703 1142788250826440703 1151654831778151421 1152780747522637695
 

Sample Output
Case #1: 4Case #2: 9Case #3: 36028797086245424
 

Source
The 36th ACM/ICPC Asia Regional Shanghai Site —— Warmup
 

Recommend
lcy

题目大意:
    从n个数中取k个数,求它们相与所得的最小值
解题思路:
    参考了大神的题解:http://blog.csdn.net/u010709592/article/details/38872515
    首先,由贪心的思想可以得到,当数越小的时候它与别的数相与得到的值越小,但是对于多个数来说,这个贪心并不是一定正确,所以还是需要,在由小到大排列后 用dfs枚举所有可能。由于最多有40个数,如果不剪枝绝对TLE。
    剪枝:如果现在的状态与后面的数全与都比之前的结果大就直接舍去(有点A*的感觉)。
附AC代码
#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;const long long INF=0x7fffffffffffffff;//所有位全为1const int maxn=40+5;long long num[maxn],A[maxn],ans;int n,k;void dfs(int pos, long long now, int have)//现在位置,与得到的值,已经使用的个数{    if(now<ans)        ans=now;    if((now&A[pos])>=ans)//如果后面全&仍然比结果大        return;    if(pos==n||have==k)//超出范围        return;    dfs(pos+1,now,have);    dfs(pos+1,now&num[pos],have+1);}int main(){    int T;    scanf("%d",&T);    for(int tt=1;tt<=T;++tt)    {        ans=INF;        scanf("%d%d",&n,&k);        for(int i=0;i<n;++i)            scanf("%lld",&num[i]);        sort(num,num+n);        A[n-1]=num[n-1];//A储存如果后面全&所得的值,用来剪枝        for(int i=n-2;i>=0;--i)            A[i]=num[i]&A[i+1];        dfs(0,INF,0);        printf("Case #%d: %lld\n",tt,ans);    }        return 0;}


1 0