P10122 [USACO18OPEN] Team Tic Tac Toe B 题解

· · 题解

这是一道强大的 if 语句题,难度大概为橙。

Despriction

给定一个 3\times 3 的“井”自行棋盘,求每一行、每一列、每一对角线中,不同的全部相等的和 2 个相等的出现的次数。

Solution

直接枚举每一行、每一列、每一对角线,然后判断即可。

这时因为大量重复代码不太美观,所以可以自定义一个 \operatorname{judge}(a,b,c) 函数。a,b,c 分别表示当前行或列或对角线的 3 个元素。

但是这题也有坑点,不仔细看清题目的可能会掉进去。

比如:

Input:

ABA
BAB
ABA

Output:

1
1

这是因为题目求的是不同的奶牛的数量,相同的可能会造成 2 次,或者更多贡献,然而实际只算 1 次。

开两个 map,第一个 f_i = 1 表示 i 已经对答案一作出贡献,反之,则没有对答案一做出贡献。

第二个 f_{i,j} = 1,表示 i,j 组队已经对答案二做出贡献,反之,则没有。

判断条件就变成了:

Code

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define rrep(i,x,y) for(int i=x;i>=y;i--)
#define sc scanf
#define pr printf
inline int read(){int s=0,w=1;char c=getchar();while(!isdigit(c)){if(c=='-') w=-1;c=getchar();}while(isdigit(c)){s=(s<<1)+(s<<3)+(c^48);c=getchar();}return s*w;}

int ans1,ans2;
char a[4][4];
map <char,bool> f,f1[100];

inline char min(char a,char b){
    return a<b?a:b;
}
inline char max(char a,char b){
    return a>b?a:b;
}
inline void judge(char cow1,char cow2,char cow3){
    if(cow1==cow2&&cow2==cow3){//三个都相等。
        if(!f[cow1]){//没有重复,则对答案一贡献加 1。
            ans1++;
            f[cow1]=1;
        }
    }
    else if(!(cow1!=cow2&&cow1!=cow3&&cow2!=cow3)){//如果不是两两不同,那么只有三个都相同或者有两个相同。因为 else 否决了一个,所以只剩下两个相同的情况。
        char c1=min(cow1,min(cow2,cow3)),c2=max(cow1,max(cow2,cow3));//比最小值和最大值,方便查找不同的元素。
        if(!f1[c1][c2]&&!f1[c2][c1]){//没有重复,则对答案二的贡献加 1。
            ans2++;
            f1[c1][c2]=f1[c2][c1]=1;
        }
    }
}
signed main(){
    rep(i,1,3)
        rep(j,1,3)
            cin>>a[i][j];
    rep(i,1,3){
        judge(a[i][1],a[i][2],a[i][3]);//行。
        //-------------------------------
        judge(a[1][i],a[2][i],a[3][i]);//列。
    }
    judge(a[1][1],a[2][2],a[3][3]);
    judge(a[1][3],a[2][2],a[3][1]);//对角线。
    pr("%lld\n%lld\n",ans1,ans2);
    return 0;
}