简称的方法只有两个: 1 第一个串的前三个, 2 第一个串的前两个+ 第二个串的前一个
然后问你 这些队伍能不能全部取到简称,并且不能重复,
题目有个限制: 如果有x 个队伍的第一种简称相同, 则这个x队伍必须选择第二种, 如果第二种也有重复的, 则NO; 并且选择第二种的 同时会对 之后的队伍选择产生影响;
解题思路; 先处理第一类相同的 (设为x), 相同的去选择第二种, x 结束后 判断这些x 是否存在相同; 如果没有相同,去处理 剩下第一类不同的(设为y),
此时对于剩下的 要判断, 之前的(x)的 是不是和现在(y)存在相同, 如果相同NO 不同 为答案,存下来
/*
题目要求:所有的队名皆不能重复,若多个队的第一类相同, 则全部选择第二类; 若
他们的第二队也有相同的 NO
在对于第一类不重复的情况下, 要对之前重复的选择第二类是否有影响
第二类 通过回溯 回溯回去看看有没有 和之前的重复 则NO
*/
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstring>
#include <stdio.h>
typedef long long ll;
using namespace std;
const int MAXN=10010;
map<string,int> cnt_first,cnt_second,cnt;//cnt 存的是正确答案
struct node
{
string first,second,ans;// 前后两个串
int id;
} num[MAXN];
int n;
int cmp(node a,node b)
{
return cnt_first[a.first]>cnt_first[b.first];// 用 统计的值 排序
}
int cmp_cnt(node a,node b)
{
return cnt[a.first]>cnt[b.first];
}
int cmp_id(node a,node b)
{
return a.id<b.id;
}
int finds(int k)
{
int i;
sort(num+k,num+n+1,cmp_cnt);// 按照答案中第一类个数排序
if(!cnt[num[k].first]) return k;// 如果第一类和第二类没有重复 结束
while(k<=n)
{
if(cnt[num[k].first])// 如果第一类的答案有
{
if(cnt[num[k].second]) return -1;//并且第二类的答案被占用 返回-1 NO
num[k].ans=num[k].second;// 没有的话 答案存第二类
cnt[num[k].ans]=1;//标记第二类答案为1
}
else
break;// 没有的话结束就可以
k++;
}
return finds(k);
}
int main()
{
int i,j;
while(~scanf("%d",&n))
{
for(i=1;i<=n; i++)
{
cin>>num[i].first>>num[i].second;
num[i].id=i;
num[i].first=num[i].first.substr(0,3);//取前三位
num[i].second=num[i].first.substr(0,2)+num[i].second[0];//取前两位+后面的第一位
cnt_first[num[i].first]++;// 统计第一种 相同的字符串 个数 ++;
}
sort(num+1,num+n+1,cmp);//按照第一个统计数值排序 第一类数值排序
int flag=0;
for(i=1;i<=n;i++)//此时已经按照第一种相同的多少从大到小排序
{
if(cnt_first[num[i].first]>1)//如果 第一种的 队伍有多个的话
{
if(cnt_second[num[i].second]==1)//判断第二种 是否被占用 no
flag=1;
else
{
num[i].ans=num[i].second;// 此时 当第一类多个, 第二类不同, 是 选择第二类为答案 全部选择第二类
cnt_second[num[i].ans]=1;// 把第二类的 这个 标记为 已用
cnt[num[i].ans]=1;// 把这个第二类的结果 在答案中标记
}
}
else// 此时说明数目相同 已经处理完了, 到i 跳出即可
break;
}
i=finds(i);// 从i 开始到结束 查找是否存在和前面有相同的部分
if(i==-1) flag=1;
if(!flag)// 第一类的 没有重复的
{
while(i<=n)
{
num[i].ans=num[i].first;
i++;
}
}
printf("%s\n",flag ?"NO":"YES");
if(!flag)
{
sort(num,num+n+1,cmp_id);//答案从小到大排序
for(i=1;i<=n;i++)
cout<<num[i].ans<<endl;
}
}
return 0;
}
123