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有关,看来有必要学一波了~

### 回答1: #include <stdio.h> int main(){ //定义一个3*3的数组用来存储棋盘 int board[3][3]={0}; int x,y,turn=1; while (1){ //打印棋盘 printf("当前棋盘:\n"); for (x=0;x<3;x++){ for (y=0;y<3;y++){ printf("%d ",board[x][y]); } printf("\n"); } //根据turn的值来判断谁轮到落子 if (turn==1){ printf("轮到X落子,请输入落子的位置(x y):"); }else { printf("轮到O落子,请输入落子的位置(x y):"); } scanf("%d %d",&x,&y); //将落子位置的值设置为对应的值 board[x][y] = turn; //改变轮到谁落子 turn = -turn; //判断谁赢了 if (board[0][0]==board[1][1] && board[1][1]==board[2][2] && board[2][2]!=0){ printf("游戏结束,获胜者是%c\n",board[0][0]==1?'X':'O'); break; } if (board[2][0]==board[1][1] && board[1][1]==board[0][2] && board[0][2]!=0){ printf("游戏结束,获胜者是%c\n",board[2][0]==1?'X':'O'); break; } for (x=0;x<3;x++){ if (board[x][0]==board[x][1] && board[x][1]==board[x][2] && board[x][2]!=0){ printf("游戏结束,获胜者是%c\n", board[x][0] == 1 ? 'X' : 'O'); break; } if (board[0][x]==board[1][x] && board[1][x]==board[2][x] && board[2][x]!=0){ printf("游戏结束,获胜者是%c\n", board[0][x] == 1 ? 'X' : 'O'); break; } } } return 0; } ### 回答2: 为了回答这个问题,需要提供题目的具体要求和规则。由于提供的信息不够具体,无法为您提供准确的代码。但是,我可以给您一个简单的Tic-tac-toe游戏的示例代码,供您参考: ```c #include <stdio.h> #include <stdbool.h> // 判断游戏是否结束 bool isGameOver(char board[][3]) { // 判断每行是否有3个相同的棋子 for(int i = 0; i < 3; i++) { if(board[i][0] != '.' && board[i][0] == board[i][1] && board[i][0] == board[i][2]) { return true; } } // 判断每列是否有3个相同的棋子 for(int i = 0; i < 3; i++) { if(board[0][i] != '.' && board[0][i] == board[1][i] && board[0][i] == board[2][i]) { return true; } } // 判断对角线是否有3个相同的棋子 if(board[0][0] != '.' && board[0][0] == board[1][1] && board[0][0] == board[2][2]) { return true; } if(board[0][2] != '.' && board[0][2] == board[1][1] && board[0][2] == board[2][0]) { return true; } return false; } // 输出棋盘 void printBoard(char board[][3]) { for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { printf("%c ", board[i][j]); } printf("\n"); } } int main() { char board[3][3]; // 初始化棋盘 for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { board[i][j] = '.'; } } int player = 1; // 玩家1先下 int row, col; while(true) { printf("Player %d's turn:\n", player); printf("Row: "); scanf("%d", &row); printf("Column: "); scanf("%d", &col); // 判断输入是否合法 if(row < 0 || row >= 3 || col < 0 || col >= 3 || board[row][col] != '.') { printf("Invalid move. Try again.\n"); continue; } // 下棋 board[row][col] = (player == 1) ? 'X' : 'O'; // 输出棋盘 printBoard(board); // 判断游戏是否结束 if(isGameOver(board)) { printf("Player %d wins!\n", player); break; } // 切换玩家 player = (player == 1) ? 2 : 1; } return 0; } ``` 这段代码实现了一个简单的命令行下的Tic-tac-toe游戏。玩家1使用'X'棋子,玩家2使用'O'棋子。玩家依次输入行和列,下棋后更新棋盘,并判断游戏是否结束。当游戏结束时,会输出获胜者并结束游戏。 ### 回答3: 题目要求实现一个井字棋游戏的判断胜负函数。给定一个3x3的井字棋棋盘,用C语言编写一个函数,判断当前是否存在某个玩家获胜或者平局。 题目要求代码中定义一个3x3的字符数组board来表示棋盘,其中 'X' 表示玩家1在该位置放置了一个棋子, 'O' 表示玩家2在该位置放置了一个棋子, '.' 表示该位置没有棋子。 下面是实现此题的C语言代码: ```c #include <stdio.h> #include <stdbool.h> // 用于使用bool类型 bool checkWin(char board[3][3]) { // 检查每一行是否有获胜的情况 for (int row = 0; row < 3; row++) { if (board[row][0] == board[row][1] && board[row][1] == board[row][2] && board[row][0] != '.') { return true; } } // 检查每一列是否有获胜的情况 for (int col = 0; col < 3; col++) { if (board[0][col] == board[1][col] && board[1][col] == board[2][col] && board[0][col] != '.') { return true; } } // 检查对角线是否有获胜的情况 if ((board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != '.') || (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != '.')) { return true; } return false; // 没有获胜的情况 } int main() { char board[3][3]; // 存储棋盘状态 // 读取棋盘状态 for (int i = 0; i < 3; i++) { scanf("%s", board[i]); } // 调用检查胜负的函数,并输出结果 if (checkWin(board)) { printf("YES\n"); } else { printf("NO\n"); } return 0; } ``` 这个程序中定义了一个函数checkWin,用于检查是否有玩家获胜。遍历棋盘的每一行、每一列和对角线,判断是否有连续相同的字符且不为'.',如果有,则返回true;否则返回false。 在主函数main中,首先定义一个3x3的字符数组board,然后通过循环从标准输入中读取棋盘状态。接着调用checkWin函数进行胜负判断,并根据结果输出"YES"或者"NO"。最后返回0表示程序正常结束。 请注意,该代码只包含了检查胜负的功能,并没有包含其他如用户输入、判断平局等功能。如果需要完整的游戏代码,请告知具体要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值