codeforces gym 101572D :BFS

题意:

给出n个k维01向量,求一个k维01向量,使得它和给定的向量组的相同位数最大值最小。

题解:

基本思路:最大值最小->最小值最大->bfs搜最小值->取最大

汉明距离:d(x,y) = x与y不同的位的个数。

(2) M i n ( M a x ( k d ( s , a i ) ) ) = M i n ( k + M a x ( d ( s , a i ) ) ) = M i n ( k M i n ( d ( s , a i ) ) ) = k + M i n ( M i n ( d ( s , a i ) ) ) = k M a x ( M i n ( s , a i ) )

于是问题变成了求一个s,使得他到给定向量组的汉明距离最小值最大。
于是bfs求每个向量到给定向量组的汉明距离最小值。
取最大的一只。


本题告诉我们:
最大值最小不一定是二分,因为可以转化成最小值最大。
而最小值最大也不一定是二分,因为可以bfs


成功的缴了智商税………于是拿出小本本记下来,以加深印象。

本题做法很多,比如打牌,或者fwt之类。。(fwt是什么啊喂,我怎么这么弱
Code:

//
// Created by calabash_boy on 18-6-15.
//
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+100;
const int INF = 0x3f3f3f3f;
int dis[1<<21];
int n,k;
char s[21];
int que[1<<21],l,r;
int main(){
    scanf("%d%d",&n,&k);
    int N = 1<<k;
    for (int i=0;i<N;i++)dis[i] = INF;
    for (int i=0;i<n;i++){
        scanf("%s",s);
        int val =0;
        for (int i=0;i<k;i++){
            val+= (s[i]=='1')*(1<<i);
        }
        dis[val]=0;
    }
    for (int i=0;i<N;i++){
        if(dis[i]==0){
            que[r++] = i;
        }
    }
    while (l<r){
        int head = que[l++];
        for (int i=0;i<k;i++){
            int temp = head^(1<<i);
            if(dis[temp]>dis[head]+1){
                dis[temp] = dis[head]+1;
                que[r++] = temp;
            }
        }
    }
    int ans =0;
    for (int i=0;i<N;i++){
        if(dis[i]>dis[ans]){
            ans =i;
        }
    }
    for (int i=0;i<k;i++){
        if(ans&(1<<i))printf("1");
        else printf("0");
    }
    return puts(""),0;
}

猜你喜欢

转载自blog.csdn.net/calabash_boy/article/details/80714060