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了。

 

原文地址:https://www.cnblogs.com/Frandy/p/google_code_making_chess_boards_python.html