题面:

C. Team Tic Tac Toe

Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 256 megabytes
 
Farmer John owns 26 cows, which by happenstance all have names starting with different letters of the alphabet, so Farmer John typically refers to each cow using her first initial – a character in the range A…ZA…Z.
The cows have recently become fascinated by the game of tic-tac-toe, but since they don’t like the fact that only two cows can play at a time, they have invented a variant where multiple cows can play at once! Just like with regular tic-tac-toe, the game is played on a 3×3 board, only instead of just Xs and Os, each square is marked with a single character in the range A...Z to indicate the initial of the cow who claims that square.
An example of a gameboard might be:

COW
XXO
ABC

The cows fill in each of the nine squares before they become confused about how to figure out who has won the game. Clearly, just like with regular tic-tac-toe, if any single cow has claimed an entire row, column, or diagonal, that cow could claim victory by herself. However, since the cows think this might not be likely given the larger number of players, they decide to allow cows to form teams of two, where a team of two cows can claim victory if any row, column, or diagonal consists only of characters belonging to the two cows on the team, and moreover if characters from both cows (not just one) are used in this row, column, or diagonal.
Please help the cows figure out how many individuals or two-cow teams can claim victory. Note that the same square on the game board might possibly be usable in several different claims to victory.
 
 
Input
The input consists of three lines, each of which is three characters in the range A...Z.
 
Output
Output should consist of two lines. On the first line, output the number of individual cows who can claim victory. On the second line, output the number of two-cow teams that could claim victory.
 
Example
Input
COW
XXO
ABC
Output
0
2
 
Note
In this example, no single cow can claim victory. However, if cows C and X team up, they can win via the C-X-C diagonal. Also, if cows X and O team up, they can win via the middle row.
 
 

题目描述:

有26头奶牛,它们的名字分别对应26个字母。最近,奶牛迷上了一款游戏,但是这款游戏只能两头牛同时玩,然后它们发明了一款可以同时多头牛玩的游戏,游戏规则大概是:每头牛都会在一个3 x 3的九宫格里面填上自己的名字,如果有一头牛能占据一整行,或一整列,或者是对角线,那么就说这头牛自称“赢”了。但是,奶牛们考虑到这样只有很少头牛能“赢”,所以,就允许两头奶牛直接组队。如果两头奶牛组队以后能“一起”(这里的“一起”指的是一定要包含两头牛)占据一整行,或一整列,或者对角线,那么,这两头牛组成的队伍“赢”了。现在要求:1.有多少头牛自称“赢”了;2.有多少支由两头牛组成的队伍“赢”了。
 

题目分析:

这道题刚开始题目没有仔细看题目,理解错了。再次看题目时发现有些情况重复计算,改了一下就AC了。
 
下面进入正题:
其实这道题一看这么小,直接暴力就能弄出来了。但是,我的想法也太暴力了,没经过任何思考,代码又长又丑。看了大神的代码才知道原来是这样写的(吐槽博主还没进入正题( ̄_ ̄|||) )。
我先讲讲我的思路(大佬略过,新人慎看,容易被误导):我写了一个检查函数,这个函数可以检测某一个字母是否包含一整行,一整列,还有对角线。然后我从字母A-Z遍历一遍就能求到问题1了,但是呢,问题2怎么求?其实只要从图中任意选两头牛出来就行了,也就是9*9=81的可能,之后用另一个临时二维数组存图,只需要把这两头牛变成同一头牛就可以用检查函数了,然后再把图还原回来,所以又写了一个还原函数。最后用vis数组标记算过的情况,然后就搞定了,AC(恶心)代码如下:
  1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 #include <cmath>
5 #include <set>
6 #include <algorithm>
7 using namespace std;
8 char mymap[5][5];
9 char temp[5][5];
10 int vis[128][128];
11
12 bool check(char ch){
13 int flag;
14 for(int i = 0; i < 3; i++){
15 flag = 1;
16 for(int j = 0; j < 3; j++){
17 if(ch != temp[i][j]) flag = 0;
18 }
19 if(flag) return true;
20 }
21
22 for(int j = 0; j < 3; j++){
23 flag = 1;
24 for(int i = 0; i < 3; i++){
25 if(ch != temp[i][j]) flag = 0;
26 }
27 if(flag) return true;
28 }
29
30 flag = 1;
31 for(int i = 0; i < 3; i++){
32 if(temp[i][i] != ch) flag = 0;
33 }
34 if(flag) return true;
35
36 flag = 1;
37 for(int i = 0; i < 3; i++){
38 if(temp[i][2-i] != ch) flag = 0;
39 }
40 if(flag) return true;
41
42 return false;
43 }
44
45 void reback(){
46 for(int i = 0; i < 3; i++){
47 for(int j = 0; j < 3; j++){
48 temp[i][j] = mymap[i][j];
49 }
50 }
51 }
52
53 void cover(char a, char b){
54 for(int i = 0; i < 3; i++){
55 for(int j = 0; j < 3; j++){
56 if(temp[i][j] == a) temp[i][j] = b;
57 }
58 }
59 }
60
61 void test(){
62 cout <<endl;
63 for(int i = 0; i < 3; i++){
64 for(int j = 0; j < 3; j++){
65 cout << temp[i][j];
66 }
67 cout << endl;
68 }
69
70 }
71
72 int main(){
73 for(int i = 0; i < 3; i++){
74 cin >> mymap[i];
75 }
76
77 reback();
78 //test();
79
80
81 char st[15];
82 int top = 0;
83
84 int cnt1 = 0;
85 for(char i = 'A'; i <= 'Z'; i++){
86 if(check(i)) { cnt1++; st[top++] = i;}
87 }
88 cout << cnt1 << endl;
89
90 for(int i = 0; i < top; i++){
91 int u1 = st[i];
92 for(int j = 0; j < top; j++){
93 int u2 = st[j];
94 vis[u1][u2] = vis[u2][u1] = 1;
95 }
96 }
97
98 int cnt = 0;
99
100
101 for(int ai = 0; ai < 3; ai++){
102 for(int aj = 0; aj < 3; aj++){
103 char ch1 = mymap[ai][aj];
104
105 for(int bi = 0; bi < 3; bi++){
106 for(int bj = 0; bj < 3; bj++){
107 char ch2 = mymap[bi][bj];
108 reback();
109 cover(ch1, ch2);
110
111 //test();
112 if(check(ch2) && !vis[ch1][ch2]) {
113 cnt++;
114 vis[ch1][ch2] = vis[ch2][ch1] = 1;
115 }
116 }
117 }
118 }
119 }
120
121 cout << cnt << endl;
122 return 0;
123 }
但是这个代码巨长(太暴力了),而且很容易出bug(足足花费1小时才写好这个水题),接下来我们讲讲大佬的优秀代码:
首先,我们可以分析一下这道题:要判断一整行,列,对角线是否被同样的牛占据,是不是只要判断一整行,列,对角线的三个元素(字母)是否相等?由此,我们就可以遍历一遍所有行,列,对角线是否被同样的牛占据,这样就可以解决问题1了。问题2呢?其实也是同样的道理:如果只有两头牛占据同一行,列,对角线,那么它们组队后就肯定是“赢”了。只要我们用数组标记这些牛(一维数组),这些  “牛”对(二维数组)被访问过,就可以通过遍历一遍数组来计算出“赢”的个数,不过这里要注意重复的问题。根据上面的想法,我们可以编写一个check函数,检查三个字母是否相等(一头牛“赢”的情况),或者是只有两个字母相等,也就是只有两种字母(对应两头牛组队“赢”的情况),然后在遍历每条边,列,对角线时都执行这个函数就可以完成这道题了。
 
补充:关于重复问题,我们可以这样想:对于一些牛,我怎样才能计算选出两头牛而且这些 "牛"对 不重复的个数,就像这样:
显然答案是C(5, 2),但是没学组合数之前,我们是不是这样算:
这样就得到了(A,B), (A,C), (A,D), (A,E)
接下来怎样算才不会重复呢?其实也就是这样:
这样我们是不是得到了(B,C), (B,D), (B, E)。之后反复执行这个操作就行了
也就是说,当我们遍历 “牛”对 (二维数组)时,通过这种方式就可以检查不同的 “牛”对 之间是否“赢”了,是不是有点神奇(ง •_•)ง,既不会漏也不会重复。怎样写见下面代码:
 
 
AC代码:
 1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 #include <cmath>
5 #include <set>
6 #include <map>
7 #include <algorithm>
8 using namespace std;
9 char g[5][5]; //图
10 int G[5][5]; //转化为整数
11 int win[30], win2[30][30]; //标记数组
12
13 void check(int a, int b, int c){
14 if(a == b && b == c) win[a] = 1; //对应一头牛“赢”的情况
15 else if(a == b && b != c) //下面两个个else if都是其中两头牛组队赢的情况
16 win2[a][c] = win2[c][a] = 1; //双向都要标记一下,去重的关键
17 else if(a == c && b != c)
18 win2[a][b] = win2[b][a] = 1;
19 else if(b == c && a != c)
20 win2[b][a] = win2[a][b] = 1;
21 }
22
23 int main(){
24 for(int i = 0; i < 3; i++) cin >> g[i];
25
26 for(int i = 0; i < 3; i++){
27 for(int j = 0; j < 3; j++){
28 G[i][j] = g[i][j]-'A'; //把字母转化为对应的数字,方便开数组
29 }
30 }
31
32 for(int i = 0; i < 3; i++){
33 check(G[i][0], G[i][1], G[i][2]); //每行
34 check(G[0][i], G[1][i], G[2][i]); //每列
35 }
36
37 check(G[0][0], G[1][1], G[2][2]); //正对角线
38 check(G[0][2], G[1][1], G[2][0]); //负对角线
39
40 int ans = 0;
41 for(int i = 0; i < 26; i++) ans += win[i]; //统计一头牛“赢”的情况
42
43 int ans2 = 0;
44 for(int i = 0; i < 26; i++){ //统计两头牛组队后“赢”的情况
45 for(int j = i+1; j < 26; j++){ //去重关键,只要遍历比i大的牛就行了
46 ans2 += win2[i][j];
47 }
48 }
49
50 cout << ans << endl << ans2 << endl;
51 return 0;
52 }
 
 
 

2019 GDUT Rating Contest III : Problem C. Team Tic Tac Toe的更多相关文章

  1. 2019 GDUT Rating Contest III : Problem D. Lemonade Line

    题面: D. Lemonade Line Input file: standard input Output file: standard output Time limit: 1 second Memo ...

  2. 2019 GDUT Rating Contest III : Problem E. Family Tree

    题面: E. Family Tree Input file: standard input Output file: standard output Time limit: 1 second Memory ...

  3. 2019 GDUT Rating Contest III : Problem A. Out of Sorts

    题面: 传送门 A. Out of Sorts Input file: standard input Output file: standard output Time limit: 1 second M ...

  4. 2019 GDUT Rating Contest II : Problem F. Teleportation

    题面: Problem F. Teleportation Input file: standard input Output file: standard output Time limit: 15 se ...

  5. 2019 GDUT Rating Contest I : Problem B. Teamwork

    题面: 传送门 B. Teamwork Input file: standard input Output file: standard output Time limit: 1 second Memor ...

  6. 2019 GDUT Rating Contest I : Problem H. Mixing Milk

    题面: H. Mixing Milk Input file: standard input Output file: standard output Time limit: 1 second Memory ...

  7. 2019 GDUT Rating Contest I : Problem A. The Bucket List

    题面: A. The Bucket List Input file: standard input Output file: standard output Time limit: 1 second Me ...

  8. 2019 GDUT Rating Contest I : Problem G. Back and Forth

    题面: G. Back and Forth Input file: standard input Output file: standard output Time limit: 1 second Mem ...

  9. 2019 GDUT Rating Contest II : Problem G. Snow Boots

    题面: G. Snow Boots Input file: standard input Output file: standard output Time limit: 1 second Memory ...

随机推荐

  1. 关于rand()

    虽然很早就知道rand是伪随机了,但是一般都懒得用srand. 直到模拟银行家算法时不用srand就造成数据实在有点假(-_-||) 所以要记得srand((int)time(0))啊

  2. 牛客网-n的约数【dfs】

    题目描述:戳这里 解题思路:这题思路好想,n最多也就是20个不同的素数相乘,把所有可能的素数找到,然后枚举素数个数就行了. n = p1^q1 + p2^q2 + p3 ^q3 + ... + pi ...

  3. PAT L2-004. 这是二叉搜索树吗?【前序遍历转化为后序遍历】

    一棵二叉搜索树可被递归地定义为具有下列性质的二叉树:对于任一结点, 其左子树中所有结点的键值小于该结点的键值: 其右子树中所有结点的键值大于等于该结点的键值: 其左右子树都是二叉搜索树. 所谓二叉搜索 ...

  4. CSS字体大小: em与px、pt、百分比之间的对比

      CSS样式最混乱的一个方面是应用程序中文本扩展的font-size属性.在CSS中,你可以用四个不同的单位度量来显示在web浏览器中的文本大小.这四个单位哪一种最适合Web? 这个问题引起了广泛的 ...

  5. 使用 js 实现一个简易版的模版引擎

    使用 js 实现一个简易版的模版引擎 regex (function test() { this.str = str; })( window.Test = ...; format() { let ar ...

  6. 使用 js 实现一个简易版的 drag & drop 库

    使用 js 实现一个简易版的 drag & drop 库 具有挑战性的前端面试题 H5 DnD js refs https://www.infoq.cn/article/0NUjpxGrqRX ...

  7. moment.js & convert timestamps to date string in js

    moment.js & convert timestamps to date string in js https://momentjs.com/ moment().format('YYYY- ...

  8. 基本ILS面的评估

    一.定义与用途 基本ILS面是ICAO DOC8168飞行程序设计规范中提到的一种限制面. 它相当于附件14中代码为3或4的精密进近跑道所规定的障碍物限制面的子集. 包含:进近面(分为两部分).过渡面 ...

  9. 磁盘使用率/文件大小查看指南du & df

    一.前言 磁盘使用率,文件大小查看是我们日常使用命令.这两个是配合使用的,磁盘使用率过高告警了,那么得找到对应的磁盘(df),然后找到对应磁盘下的哪个目录和文件占用了空间(du). df(Disk f ...

  10. Java中print、printf、println的区别

    Java中print.printf.println的区别 区别 print:标准输出,但不换行,不可以空参: println:标准输出,但会自动换行,可以空参,可以看做:println()相当于pri ...