• E. Almost Fault-Tolerant Database 暴力枚举 + 分类讨论 + 思维 Codeforces Round #704 (Div. 2)


    E. Almost Fault-Tolerant Database 暴力枚举 + 分类讨论 + 思维

    题目大意:

    给你 (n) 个单元,每一个单元是一个长度为 (m) 的序列,让你构造一个单元 (ans) ,满足 (ans) 这个单元和给定的 (n) 个单元的每一个单元最多有两个位置的数不一样,如果存在这个单元,输出 "Yes" 并输出这个单元,如果没有则输出 "No"

    题解:

    首先假设答案就是 第一个单元,然后和其他以一比对,进行分类讨论:

    • 如果和其他最多不同 (dif<=2) 那么直接输出答案
    • 如果 (dif>4) ,那么不可能构造出来
    • 如果 (dif==3||dif==4) 则要暴力枚举,首先找到那个 (dif) 最大的位置,(假设我枚举改动 (dif) 最大的这个位置),其中至少有一个位置是要变成第一个单元的,然后如果 (dif==4) ,那么另一个位置也要和第一个单元相同,如果 (dif==3) ,那么就在后面比较的过程中寻找另一个要变化的位置,但是容易发现可以把 (dif==3)(dif==4) 归在一类

    这个题目其实发现任意两个单元最多只有4个是不一样的这个是很简单的,但是发现这个之后想到直接暴力枚举,如果 (dif==4) ,那么毫无疑问,直接暴力枚举两个相同即可。

    但是 (dif==3) ,那么除了要有一个和第一个单元相同,还会有一个是不固定的答案,也就是一个变量,需要在后面比较的时候获得,这个需要注意!

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 3e5+10;
    vector<vector<int>>a;
    int n,m;
    vector<int> Diff(int x,int y){
        vector<int>ans;
        for(int i=0;i<m;i++){
            if(a[x][i]!=a[y][i]) ans.push_back(i);
        }
        return ans;
    }
    bool check(vector<int>&tmp){
        for(int i=0;i<n;i++){
            int cnt = 0,pos = -1;
            for(int j=0;j<m;j++){
                if(a[i][j]!=tmp[j]) cnt++;
                if(tmp[j]==-1) pos = j;
            }
            if(cnt>3) return false;
            if(cnt==3){
                if(pos!=-1) tmp[pos] = a[i][pos];
                else return false;
            }
        }
        return true;
    }
    void Print(vector<int>tmp){
        printf("Yes
    ");
        for(int i=0;i<tmp.size();i++) {
            if(tmp[i]==-1) printf("1 ");
            else printf("%d ",tmp[i]);
        }
        printf("
    ");
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
            vector<int>v;
            for(int j=0,x;j<m;j++){
                scanf("%d",&x);
                v.push_back(x);
            }
            a.push_back(v);
        }
        int mx_id = 0,dif = 0;
        for(int i=1;i<n;i++){
            int res = Diff(0,i).size();
            if(res>dif) dif = res,mx_id = i;
        }
        if(dif<=2) Print(a[0]);
        else if(dif>4) printf("No
    ");
        else{
            vector<int> now = Diff(0,mx_id);
            for(int i=0;i<now.size();i++){
                for(int j=i+1;j<now.size();j++){
                    vector<int>tmp = a[mx_id];
                    int x = now[i],y = now[j];
                    tmp[x] = -1,tmp[y] = a[0][y];
                    if(check(tmp)){
                        Print(tmp);
                        return 0;
                    }
                    tmp[x] = a[0][x],tmp[y] = -1;
                    if(check(tmp)){
                        Print(tmp);
                        return 0;
                    }
                }
            }
            printf("No
    ");
        }
    }
    
  • 相关阅读:
    《剑指offer》 面试题43 n个骰子的点数 (java)
    《剑指offer》面试题45 圆圈中最后剩下的数字(Java版本)
    《剑指offer》面试题39 二叉树的深度(java)
    《剑指offer》面试题32----从1到n整数中1出现的次数
    快速排序思路整理
    《Java程序猿面试宝典》之字符串
    Tomcat的server.xml
    easyui combobox 清除选中项目 和 清空option选项
    2019
    throw UnsupportedOperationException
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/14442685.html
Copyright © 2020-2023  润新知