程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 暴力或隨機-hdu-4712-Hamming Distance

暴力或隨機-hdu-4712-Hamming Distance

編輯:C++入門知識

題目大意:   求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;  
}  

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved