google code jam exercise——Making Chess Boards(1)
Round 1C 2010的最后一题。C轮果然还是有些难度的,虽然我觉得第一题比较简单。
这题是给定一大块板子,上面有黑块和白块,跟Chess Board上面的方格类似。要求将上面存在的Chess Board剪下来,从大到小。
直接的方法,size从最大到最小,扫描整个板子,选取size大小的块进行匹配,如果满足,那么将这一块剪下来。
存在的几个问题,
1. 数据的读取
给定的是16进制数据,每一位表示一个块,0和1表示是黑块还是白块。需要将其转化为一位一位的形式。
这里采用的方法是bin(ord(s)-ord("A")+10),先把A~F转化成数字,然后转化成二进制数,再把二进制数的每一位放进list。
2. 块匹配
pattern=[[(i+j)%2 for j in range(size)] for i in range(size)],即生成了一个size x size大小的Chess Board,对给定的板子matrix,当左上角的位置扫描到(i,j)时,
那么比较matrix[i:i+size][j:j+size],如果匹配,则将这一块的数据置-1,表示不可用了,后面匹配的块不会与这一块有覆盖的。
需要注意的是matrix[i:i+size][j:j+size]得到的结果与期望的不符,需要用其它方式得到这个以(i,j)为左上角,size x size的块。
代码如下:
#!/usr/bin/python #encoding:UTF-8 #Filename:MakingChessBoards.py import sys def matchPattern(matrix,i,j,size,pattern0,pattern1): testMatrix = [line[j:j+size] for line in matrix[i:i+size]] matchFlag = 0 if testMatrix[0][0]!=pattern0[0][0]: if testMatrix==pattern1: matchFlag = 1 else: if testMatrix==pattern0: matchFlag = 1 if matchFlag ==1: for ti in range(i,i+size): for tj in range(j,j+size): matrix[ti][tj] = -1 return [matchFlag,matrix] def toBinLst(a): lst=[] for s in a: b = [] if(s>="A"): b = bin(ord(s)-ord("A")+10) elif(s>="a"): b = bin(ord(s)-ord("a")+10) else: b = bin(ord(s)-ord("0")) b = b.replace("0b","") if(len(b)<2): b = "000" + b elif(len(b)<3): b = "00" + b elif(len(b)<4): b = "0" + b for val in b: lst.append(int(val)) return lst def solveCase(caseData,m,n): mn = m; if n<mn: mn = n cnt = [] for size in range(mn,0,-1): pattern0 = [[(i+j)%2 for j in range(size)] for i in range(size)] pattern1 = [[(i+j+1)%2 for j in range(size)] for i in range(size)] cntThisSize = 0 for i in range(m-size+1): for j in range(n-size+1): matchResult = matchPattern(caseData,i,j,size,pattern0,pattern1) if matchResult[0]==1: cntThisSize = cntThisSize + matchResult[0] matrix = matchResult[1] if cntThisSize !=0: cnt.append([size,cntThisSize]) total = len(cnt) return [total,cnt] inname = "input.txt" outname = "output.txt" if len(sys.argv)>1: inname = sys.argv[1] outname = inname.rstrip(".in") outname = outname + ".out" fin = open(inname,"r") fout = open(outname,"w") testCaseNum = int(fin.readline().rstrip("\n")) for caseNum in range(testCaseNum): (m,n) = [int(val) for val in fin.readline().rstrip("\n").split()] caseData = [] for lineNum in range(m): line = fin.readline().rstrip("\n") caseData.append(toBinLst(line)) result = solveCase(caseData,m,n) answer = "Case #%d: %d\n" %(caseNum+1,result[0]) for key,value in result[1]: answer = answer + str(key) + " " + str(value) + "\n" fout.write(answer) fin.close() fout.close()
测试结果中,small case正确,large case没有跑出来。算法复杂度需要改进。
看了一下测试文件,最后两个case的size都是512x512,难怪卡在第99个case了。