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
ight] land i
eq 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);
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
",ans);
}
Wrong Answer Cases
Test 3
What I Learn
这种解法实际上要求构造一个不合法的输入,根据这个不合法的输入,推断出(k)的要求。
核心就是(k)和不合法的输入是关联的。