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

     

  • 相关阅读:
    Liunx命令集
    Jenkins,tomcat和jdk安装步骤
    《九悦学车》和《忠金融·惠生活》BUG表
    2020年12月17日总结
    思维导图加上测试用例
    2020年12月15日总结
    双肩包、椅子和电梯的测试用例(测试题)
    fastadmin 前台关联搜索
    composer安装阿里云短信
    php 生成订单号
  • 原文地址:https://www.cnblogs.com/Frandy/p/google_code_making_chess_boards_python.html
Copyright © 2020-2023  润新知