coeofrces 637C Problem Analysis

Codeforces Tutorial

C. Promocodes with Mistakes

Problem Analysis

题意:有n个长度均为6的校验码,要求最大的容错率k,使得对于任意一个校验码都可以判定其在不超过k个错误下为这n个校验码中的哪一个 。
之前没遇到过这种类型,学习了。
我们可以采用逆向思维来思考这个问题。
两个字符串的差异:

\[strdif(s_1,s_2)=\sum_{k=0}^5 s_1[k]!=s_2[k] \]

对于任意的两个\(s_i\)\(s_j\),假设存在一个字符串 \(s_k\),和一个不合法的\(k\),使得

\[strdif(s_i,s_k) \leq k \land strdif(s_j,s_k) \leq k \]

\[strdif(s_i,s_j) \leq strdif(s_i,s_k)+strdif(s_j,s_k) \leq 2k \]

所以:

不合法的

\[k \ge \frac{strdif(s_i,s_j)+1}{2} \]

那么合法的

\[k \leq \frac{strdif(s_i,s_j)-1}{2} ,for \quad i,j \in \left[1,n\right] \land i \neq j \]

Acepted Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
#include<map>
#include<istream>
#include<cassert>
#include<set>
#define DEBUG(x) cout<<#x<<" = "<<x<<endl
#define DEBUG2(x,y) cout<<#x<<" = "<<x<<" , "\
<<#y<<" = "<<y<<endl
using namespace std;
typedef long long ll;
int n;
char promocode[1100][10];
int strdif(char a[],char b[])
{
    int cnt=0;
    for(int ii=0;ii<6 ;ii++ ){
        if(a[ii]!=b[ii])cnt++;
    }
    return cnt;
}
int main()
{
//    freopen("in.txt","r",stdin);
    scanf("%d\n",&n);
    for(int ii=1;ii<=n ;ii++ ){
        scanf("%s",promocode[ii]);
    }
    int ans=6;
    for(int ii=1;ii<=n-1 ;ii++ ){
        for(int jj=ii+1;jj<=n ;jj++ ){
            ans=min(ans,(strdif(promocode[ii],promocode[jj])-1)/2);
        }
    }
    printf("%d\n",ans);
}

Wrong Answer Cases

Test 3

ans 的默认设置问题

What I Learn

这种解法实际上要求构造一个不合法的输入,根据这个不合法的输入,推断出\(k\)的要求。
核心就是\(k\)和不合法的输入是关联的。

Reference

https://blog.csdn.net/V5ZSQ/article/details/70854480

posted @ 2019-06-01 15:56  MalcolmMeng  阅读(120)  评论(0编辑  收藏  举报