codeforce D. Innokenty and a Football League 貪心,模擬

題目:

Innokenty is a president of a new football league in Byteland. The first task he should do is to assign short names to all clubs to be shown on TV next to the score. Of course, the short names should be distinct, and Innokenty wants that all short names consist of three letters.

Each club's full name consist of two words: the team's name and the hometown's name, for example, "DINAMO BYTECITY". Innokenty doesn't want to assign strange short names, so he wants to choose such short names for each club that:

  1. the short name is the same as three first letters of the team's name, for example, for the mentioned club it is "DIN",
  2. or, the first two letters of the short name should be the same as the first two letters of the team's name, while the third letter is the same as the first letter in the hometown's name. For the mentioned club it is "DIB".

Apart from this, there is a rule that if for some club x the second option of short name is chosen, then there should be no club, for which the first option is chosen which is the same as the first option for the club x. For example, if the above mentioned club has short name "DIB", then no club for which the first option is chosen can have short name equal to "DIN". However, it is possible that some club have short name "DIN", where "DI" are the first two letters of the team's name, and "N" is the first letter of hometown's name. Of course, no two teams can have the same short name.

Help Innokenty to choose a short name for each of the teams. If this is impossible, report that. If there are multiple answer, any of them will suit Innokenty. If for some team the two options of short name are equal, then Innokenty will formally think that only one of these options is chosen.

Input

The first line contains a single integer n (1 ≤ n ≤ 1000) — the number of clubs in the league.

Each of the next n lines contains two words — the team's name and the hometown's name for some club. Both team's name and hometown's name consist of uppercase English letters and have length at least 3 and at most 20.

Output

It it is not possible to choose short names and satisfy all constraints, print a single line "NO".

Otherwise, in the first line print "YES". Then print n lines, in each line print the chosen short name for the corresponding club. Print the clubs in the same order as they appeared in input.

If there are multiple answers, print any of them.

Examples
input
2
DINAMO BYTECITY
FOOTBALL MOSCOW
output
YES
DIN
FOO
input
2
DINAMO BYTECITY
DINAMO BITECITY
output
NO
input
3
PLAYFOOTBALL MOSCOW
PLAYVOLLEYBALL SPB
GOGO TECHNOCUP
output
YES
PLM
PLS
GOG
input
3
ABC DEF
ABC EFG
ABD OOO
output
YES
ABD
ABE
ABO

這個題,哎~糾結了好幾天,一直不知道那錯了,我開始採用的策略是這樣:首先考慮前面的名字相同的,那麼這些只能選後面的,如果後面的有重複就無解,然後再跑一圈,

考慮前面的,看是不是被佔,如果被佔就往後摞一摞,如果還被佔也無解。這個是錯的,感謝ZJ學姐的樣例:
 4
abc def
abc ghi
abo xyz
abg opq
仔細分析,原因是對於不確定的元素,不能貿然決定,直到把所有沒有爭議的選完後,才能瞎選,你在前面瞎選會對後面產生影響。
code:
#include<cstring>
#include<cstdio>
#include<map>
#include<string>
using namespace std;
char name[25],home[25];
char op0[1005][5],op2[1005][5];
char ans[1005][5];
int main(){
    int N;
    while(scanf("%d",&N)==1){
        for(int i=0;i<N;++i){
            scanf("%s%s",name,home);
            op0[i][0]=name[0];op0[i][1]=name[1];
            op0[i][2]=name[2];op0[i][3]='\0';
            op2[i][0]=name[0];op2[i][1]=name[1];
            op2[i][2]=home[0];op2[i][3]='\0';
        }
        map<string,int>cnt;
        for(int i=0;i<N;++i){
            cnt[op0[i]]++;
        }
        map<string,bool>visit;
        bool noAns=false;
        for(int i=0;i<N;++i){
            if(cnt[op0[i]]>=2){
                if(!visit[op2[i]]){
                    strcpy(ans[i],op2[i]);
                    visit[op2[i]]=true;
                }else{
                    noAns=true;
                }
            }
            //printf("%d\n",noAns);
        }
        for(int j=0;j<N;++j){//最差情況下的循環次數
            bool update=false;//標記更新了沒
            for(int i=0;i<N;++i){
                if(!strlen(ans[i])){
                    if(!visit[op0[i]]&&!visit[op2[i]])continue;
                    if(visit[op0[i]]&&!visit[op2[i]]){
                        strcpy(ans[i],op2[i]);
                        visit[op2[i]]=true;update=true;
                    }else if(visit[op2[i]]&&!visit[op0[i]]){
                        strcpy(ans[i],op0[i]);
                        visit[op0[i]]=true;update=true;
                    }else noAns=true;
                }
            }
            if(!update)break;
        }
        for(int i=0;i<N;++i){
            if(!strlen(ans[i]))strcpy(ans[i],op0[i]);
        }
        if(noAns)printf("NO\n");
        else{
            printf("YES\n");
            for(int i=0;i<N;++i)
                printf("%s\n",ans[i]);
        }
    }
}

另外貼一下看的別人的代碼,思路大體上差不多,但寫得挺漂亮的:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000+5;
string a[maxn], b[maxn],ans[maxn];
bool hasAns[maxn];
set<string> used;
void f(string s){
    if(used.count(s)){cout << "NO"<<endl; exit(0);}
}
int main(){
    int n;
    cin >> n;
    for(int i = 0; i < n; i++){
        string s1,s2;
        cin >> s1 >> s2;
        a[i] = s1.substr(0, 3);
        b[i] = s1.substr(0, 2) + s2.substr(0, 1);
    }


    for(int i = 0; i < n; i++)
        for(int j = 0; j < i; j++)
            if(a[i] == a[j])
                hasAns[i] = hasAns[j] = 1;//具有相同第一個名字的
    for(int i = 0; i < n; i++){
        if(hasAns[i]){
            f(b[i]);
            ans[i] = b[i];
            used.insert(b[i]);
        }
    }
    
    for(int j = 0; j < n; j++){//j代表最差情況,需要循環次數
        for(int i = 0; i < n; i++){
            if(hasAns[i]) continue;//已經有答案了
            if(used.count(a[i])){//a[i]已經被用
                f(b[i]);
                ans[i] = b[i];
                used.insert(b[i]);
                hasAns[i] = 1;
            }
        }
    }
    for(int i = 0; i < n; i++)
        if(!hasAns[i])
            ans[i] = a[i];
    cout << "YES\n";
    for(int i = 0; i < n; i++) cout << ans[i] << endl;
    return 0;
}
另外,據說此題與2_SAT有關,看來有必要學一波了~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章