Codeforce 780D Innokenty and a Football League (贪心+模拟)
简称的方法只有两个: 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
岂曰无衣?与子同袍。王于兴师,修我戈矛。与子同仇!
岂曰无衣?与子同泽。王于兴师,修我矛戟。与子偕作!
岂曰无衣?与子同裳。王于兴师,修我甲兵。与子偕行!