[ 题解 ] [ 集合 ] C. Team Tic Tac Toe (待更名)

http://codeforces.com/group/NVaJtLaLjS/contest/238202/problem/C


题意:

打井都玩过吧,3*3个格,放置一行一列或者一对角线就能赢的那个。

现在农夫的牛在玩一个新版打井,这个打井不是两人玩,而是26只牛在玩,这26牛用26个大写字母来表示。

现在要求输出两个答案:单独一头牛获胜的有多少只,两头牛一起获胜的有多少对。两个答案互不影响。比如:

XUW
CCC
XPX 

答案是12。单独一头牛获胜的只有C,这个大家都懂;

两头牛一起获胜的有CXPX,因为第一列只有CX,第三行只有PX。对角线CX是获胜了,但是这个组合重复了。

示例:

Input

COW
XXO
ABC

Output

0
2

注意重复!

Input

CCC
CXD
XXD

Output

1
3

题意我应该描述得很清楚了,时间1s非常充足,输入数据也仅仅9个,用怎样的算法都不会超时,除非你硬要在里面跑个26^9全排列;要不然我有闲工夫用脚本做题?


行列对角线判断大家都会,行列两个循环加对角线两个条件判断就可以完成。不过要怎么处理重复的获胜者?


以前刚学C的思路就是,用一个数组winner来存26只牛是否获胜,X获胜就把winner[X]赋值为1,最终检查winner数组中有多少个1


后来见过队列集合映射等数据结构后,这种不计重复的题一般会用集合来做了。


用数组当然也可以,不过集合没有固定大小,并且里面的元素已经从小到大排序。遇到需要依次输出答案的题目,集合就非常方便。

另外,有时候在大数组中寻找元素可能相当耗时,使用集合可以快速地对元素进行操作。


这篇题解只是简单地展示集合的去重与排序作用。不熟悉C++的同学(比如本蒟蒻)不用担心,本蒟蒻写不出什么C++代码,只会拿Ruby数组来充当集合。

(而且这里的排序与去重功能还是手动启用的,操作后数组就变集合了)


我来稍微解释一下这些代码:


输入:就是输入,这个数组跟C语言的char board[3][3]是一样的;


=begin

被注释掉的代码

=end


前面很难看的四段重复代码:

假如三个字母相同,把这个字母加入winner

去重计数输出答案;(集合的去重与获知元素数量特点)


后面很难看的四段重复代码:

假如三个字母去重后只有两个,当字符串加入winner;(小的字母在前,集合的排序特点)

去重计数输出答案。


(看过算法书算法教程的同学可能觉得这是伪代码,特别是for的那段。脚本语言确实有点像伪代码就是了...


我加了查看元素的代码,会输出这样的信息:(示例2)

["C"]
1
["CX", "CX", "DX", "CD", "CX"]
3 

可以看到CX的组合赢了三次,去重后只剩下一个,最终集合只有三个元素。

注意这里的CX都是排序过的。CX之间只是一个组合而没有循序之分,不妨人为规定小的在前,这样保证不会出现"CX""XC"这种重复。


蒟蒻极少写注释,不知能否帮到你:

  1 ## 输入的二维数组
  2 board = Array.new ;
  3 board.push( Array.new( gets.split('') ) ) ;
  4 board.push( Array.new( gets.split('') ) ) ;
  5 board.push( Array.new( gets.split('') ) ) ;
  6 
  7 =begin
  8 for i in 0..2
  9     for j in 0..2
 10         puts board[i][j] ;
 11     end
 12 end
 13 =end
 14 
 15 ## 这个数组用来存获胜者
 16 winner = Array.new ;
 17 
 18 for i in 0..2
 19     
 20     ## 占据一行获胜,把字母加入数组
 21     if board[i][0]==board[i][1] && board[i][0]==board[i][2] 
 22         winner.push( board[i][0] ) ;
 23     end
 24     
 25     ## 占据一列获胜,把字母加入数组
 26     if board[0][i]==board[1][i] && board[0][i]==board[2][i] 
 27         winner.push( board[0][i] ) ;
 28     end
 29     
 30 end
 31 
 32 if board[0][0]==board[1][1] && board[0][0]==board[2][2] 
 33     winner.push( board[0][0] ) ;
 34 end
 35 ## 两个对角线
 36 if board[0][2]==board[1][1] && board[0][2]==board[2][0] 
 37     winner.push( board[0][0] ) ;
 38 end
 39 
 40 ## 查看winner的元素
 41 print "#{winner}"+"\n" ;
 42 
 43 ## 这个表示去除数组中重复的元素
 44 winner.uniq! ;
 45 
 46 ## 输出数组的大小
 47 puts winner.size ;
 48 
 49 ## 清空数组
 50 winner.clear ;
 51 
 52 ## 临时字符数组
 53 tmpStr = Array.new ;
 54 
 55 for i in 0..2
 56     
 57     ## 把三个字母加入数组,去重后如果数组中只有两个元素,排列后加入winner
 58     tmpStr.push( board[i][0],board[i][1],board[i][2] );
 59     tmpStr.uniq! ;
 60     if tmpStr.size == 2 
 61         tmpStr.sort! ;
 62         winner.push( tmpStr.join );
 63     end
 64     tmpStr.clear ;
 65     
 66     ## 同上
 67     tmpStr.push( board[0][i],board[1][i],board[2][i] );
 68     tmpStr.uniq! ;
 69     if tmpStr.size == 2 
 70         tmpStr.sort! ;
 71         winner.push( tmpStr.join );
 72     end
 73     tmpStr.clear ;
 74     
 75 end
 76 
 77 tmpStr.push( board[0][0],board[1][1],board[2][2] );
 78 tmpStr.uniq! ;
 79 if tmpStr.size == 2 
 80     tmpStr.sort! ;
 81     winner.push( tmpStr.join );
 82 end
 83 tmpStr.clear ;
 84 ## 对角线,同上
 85 tmpStr.push( board[2][0],board[1][1],board[0][2] );
 86 tmpStr.uniq! ;
 87 if tmpStr.size == 2 
 88     tmpStr.sort! ;
 89     winner.push( tmpStr.join );
 90 end
 91 tmpStr.clear ;
 92 
 93 ## 查看winner的元素
 94 puts "#{winner}" ;
 95 
 96 ## 数组去重,因为元素排列过所以不会重复
 97 winner.uniq! ;
 98 
 99 ## 输出数组的大小
100 puts winner.size ;

没有高亮估计特别难看吧...

猜你喜欢

转载自www.cnblogs.com/Kaidora/p/10526396.html