题面:

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. 1009E Intercity Travelling 【数学期望】

    题目:戳这里 题意:从0走到n,难度分别为a1~an,可以在任何地方休息,每次休息难度将重置为a1开始.求总难度的数学期望. 解题思路: 跟这题很像,利用期望的可加性,我们分析每个位置的状态,不管怎么 ...

  2. SPOJ LCS Longest Common Substring(后缀自动机)题解

    题意: 求两个串的最大\(LCS\). 思路: 把第一个串建后缀自动机,第二个串跑后缀自动机,如果一个节点失配了,那么往父节点跑,期间更新答案即可. 代码: #include<set> # ...

  3. js optional chaining operator

    js optional chaining operator js 可选链 可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效. ?. 操作符的功能类似于 ...

  4. prefetch & preload & prerender & dns-prefetch & preconnect

    prefetch & preload & prerender & dns-prefetch & preconnect performance optimization ...

  5. jest ignore

    jest ignore modulePathIgnorePatterns https://jestjs.io/docs/en/configuration modulePathIgnorePattern ...

  6. 没想到即将上线的NGK生态应用这么厉害?!

    话说这即将上线的NGK公链可不是闹着玩的,这条公链的蛰伏时间长达两年,恐怕这个准备时间,连最初的区块链1.0时代的项目都无法比拟,现在的话那都差太远了. 编程一段代码并不难,难的是耐得住赚快钱的心.人 ...

  7. Fast R-CNN训练自己的数据集时遇到的报错及解决方案

    最近使用Fast R-CNN训练了实验室的数据集,期间遇到一些报错,主要还是在配置环境上比较麻烦,但可以根据提示在网上找到解决这些错误的办法.这里我只记录一些难改的报错,以后再遇见这些时希望能尽快解决 ...

  8. CodeMirror动态修改代码(关键: editor.getDoc().setValue(data); editor.refresh();)

    在使用codemirror时,其原理是根据form中的textarea标签,自动加载其内容,获得代码行的显示.(具体使用方式参见 codemirror官网使用手册 http://codemirror. ...

  9. canal数据同步的环境配置

    canal数据同步的环境配置:(适用于mysql) 前提:在linux和windows系统的mysql数据库中创建相同结构的数据库和表,我的linux中mysql是用docker实现的(5.7版本), ...

  10. CentOS7集群环境Elastic配置

    CentOS7集群环境Elastic配置 (首先去官网下载elasticsearch的source code并解压到/usr/soft目录下) (以下默认root账户) 1.更改配置文件 文件路径:/ ...