当前位置:编程学习 > C/C++ >>

暴力或随机-hdu-4712-Hamming Distance

题目大意:
 
求n个20位0、1二进制串中,两两抑或最少的1的个数。
 
解题思路:
 
两种解法:
 
1、20位 一共有1<<20个状态,先预处理1的个数,并把相同的1的个数的状态放到一个集合里。根据0和其它数抑或得相同,1和其它数抑或得反,从小到大枚举1的个数的状态P,用其中一个串A来和P相抑或,得到B ,如果B在给定的串中,说明A^B中1的个数为P中1的个数。
 
这种解法的最坏时间复杂度为C(20,10)*n*20  很暴力,数据很弱。
 
代码:
#include<iostream>  
#include<cmath>  
#include<cstdio>  
#include<cstdlib>  
#include<string>  
#include<cstring>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<set>  
#include<stack>  
#include<list>  
#include<queue>  
#define eps 1e-6  
#define INF 0x3fffffff  
#define PI acos(-1.0)  
#define ll __int64  
#define lson l,m,(rt<<1)  
#define rson m+1,r,(rt<<1)|1  
#pragma comment(linker, "/STACK:1024000000,1024000000")  
using namespace std;  
  
#define Maxn 110000  
//0和a抑或得相同  
//1和a抑或得相反  
bool hav[1<<20];  
vector<int>myv[25]; //myv[i]表示含有i个1的状态  
int sa[Maxn];  
  
int main()  
{  
   int t,n;  
  
   for(int i=0;i<(1<<20);i++)  
   {  
       int num=0;  
       for(int j=0;j<20;j++)  
          if(i&(1<<j))  
            num++;  
       myv[num].push_back(i); //含1的个数相同的状态放到一个集合里  
   }  
   scanf("%d",&t);  
   while(t--)  
   {  
       scanf("%d",&n);  
       memset(hav,false,sizeof(hav));  
       bool flag=false;  
       for(int i=1;i<=n;i++)  
       {  
           scanf("%X",&sa[i]);  
           if(hav[sa[i]])  
              flag=true;  
           else  
              hav[sa[i]]=true;  
       }  
       if(flag)  
       {  
           puts("0");  
           continue;  
       }  
       for(int i=1;i<=20&&!flag;i++)  
            for(int j=1;j<=n&&!flag;j++)  
            {  
                for(int k=0;k<myv[i].size()&&!flag;k++)  
                {  
                    if(hav[sa[j]^myv[i][k]])  
                    {  
                        printf("%d\n",i);  
                        flag=true;  
                    }  
                }  
            }  
   }  
   return 0;  
}  

 

 
2、因为最终结果肯定在1~20之间,结果域较小。得到结果的概率较大,所以随机两个串的标号,直接计算就可以,随机1000000次。预处理会减少枚举次数。
 
代码:

 
#include<iostream>  
#include<cmath>  
#include<cstdio>  
#include<cstdlib>  
#include<string>  
#include<cstring>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<set>  
#include<stack>  
#include<list>  
#include<queue>  
#define eps 1e-6  
#define INF 0x3fffffff  
#define PI acos(-1.0)  
#define ll __int64  
#define lson l,m,(rt<<1)  
#define rson m+1,r,(rt<<1)|1  
#pragma comment(linker, "/STACK:1024000000,1024000000")  
using namespace std;  
  
#define Maxn 110000  
int sa[Maxn];  
bool hav[1<<20];  
  
int Cal(int a)  
{  
    int res=0;  
  
    while(a)  
    {  
        if(a&1)  
            res++;  
        a>>=1;  
    }  
    return res;  
}  
int main()  
{  
   int t,n;  
  
   scanf("%d",&t);  
   while(t--)  
   {  
       scanf("%d",&n);  
       memset(hav,false,sizeof(hav));  
       bool flag=false;  
       for(int i=1;i<=n;i++)  
       {  
           scanf("%X",&sa[i]);  
           if(hav[sa[i]])  
              flag=true;  
           else  
              hav[sa[i]]=true;  
       }  
       if(flag)  
       {  
           printf("0\n");  
           continue;  
       }  
       int ans=20;  
      // srand((unsigned)time(NULL));  
       for(int i=1;i<=1000000;i++)  
       {  
           int j=rand()%n+1;  
           int k=rand()%n+1;  
           if(j==k)  
              continue;  
           ans=min(ans,Cal(sa[j]^sa[k]));  
       }  
       printf("%d\n",ans);  
  
  
   }  
   return 0;  
}  

 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,