http://codeforces.com/group/NVaJtLaLjS/contest/238202/problem/C
题意:
打井都玩过吧,3*3个格,放置一行一列或者一对角线就能赢的那个。
现在农夫的牛在玩一个新版打井,这个打井不是两人玩,而是26只牛在玩,这26牛用26个大写字母来表示。
现在要求输出两个答案:单独一头牛获胜的有多少只,两头牛一起获胜的有多少对。两个答案互不影响。比如:
XUW
CCC
XPX
答案是1与2。单独一头牛获胜的只有C,这个大家都懂;
两头牛一起获胜的有CX与PX,因为第一列只有C与X,第三行只有P与X。对角线C与X是获胜了,但是这个组合重复了。
示例:
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
可以看到C和X的组合赢了三次,去重后只剩下一个,最终集合只有三个元素。
注意这里的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 ;
没有高亮估计特别难看吧...