Search code examples
pythonalgorithmrecursionlogic

CP Python Logic Confusion on Modern Art (Bronze USACO 2017 US Open p.3)


Problem Info

USACO 2017 US Open Bronze Problem 3 Modern Art Problem Link

My Work

# Read in grid as 2D array
with open("art.in", 'r') as fin:
    n = int(fin.readline().strip())
    grid = [[int(i) for i in fin.readline().strip()] for _ in range(n)]
print(grid)

# Get all possible colors, which is everything visible excluding zero
possible = set()
for row in grid:
    for p in row:
        possible.add(p)
if 0 in possible:
    possible.remove(0)
print(possible)

# Recursive search function that gets the maximum x of the triangle and maximum y of the triangle, which will be used further down the road to calculate whether or not it is a valid rectangle
def search(grid, i, j, v):
    global max_x, max_y, searched, area
    if i < 0 or i >= n or j < 0 or j >= n or grid[i][j] != v or (i, j) in searched:
        max_x = max(max_x, j)
        max_y = max(max_y, i)
        return
    searched.append((i, j))
    area += 1
    search(grid, i+1, j, v)
    search(grid, i-1, j, v)
    search(grid, i, j+1, v)
    search(grid, i, j-1, v)

# Use the search, and check if there is a possibility of the rectangle being covered. It it is covered, eliminate the rectangle that covers it from the list of possibilities.
searched = []
for i, row in enumerate(grid):
    for j, p in enumerate(row):
        if (i, j) in searched or not p:
            continue
        max_x = 0 
        max_y = 0
        # The area variable is uneeded. Using it for debugging
        area = 0
        search(grid, i, j, p)
        print(area, (max_x-j) * (max_y-i))
        print()

        for k in range(i, max_y):
            for l in range(j, max_x):
                if grid[k][l] != p and grid[k][l] in possible:
                    possible.remove(grid[k][l])

# Write the answer to the output file
with open('art.out', 'w') as fout:
    fout.write(str(len(possible)))

Problem

My logic is pretty clear from the code, and I can get 6 out of 10 test cases, but when I try an input like:

4
1234
1234
1234
1334

My program outputs 4 instead of 3, which is the correct answer. Therein lies my problem. I have no idea why it is 3 and not 4

What I've Tried

I've read over the problem multiple times, and I still don't get it.

If anyone could help explain it, that would be great.


Solution

  • I asked my teacher and he gave me this:

    with open('art.in', 'r') as fin:
        n=int(fin.readline().strip())
        grid=[[int(i) for i in fin.readline().strip()] for _ in range(n)]
    
    rect=[]
    for clr in range(10):
        rect.append([n,n,-1,-1])
    
    # Find out rect for each color
    for i in range(n):
        for j in range(n):
            a=grid[i][j]
            if a>0:
                rect[a][0]=min(rect[a][0],i)
                rect[a][1]=min(rect[a][1],j)
                rect[a][2]=max(rect[a][2],i)
                rect[a][3]=max(rect[a][3],j)
    
    ans=0
    not_original=[0]*10
    for clr in range(10):
        if rect[clr][0]<n:
            ans=ans+1
            # any color inside another rect cannot be original color
            for i in range(rect[clr][0], rect[clr][2]+1):
                for j in range(rect[clr][1], rect[clr][3]+1):
                    if grid[i][j]!=clr:
                        not_original[grid[i][j]]=1
    
    with open("art.out", 'w') as fout:
        fout.write(str(ans-sum(not_original)))
    

    The main difference is that I forgot that each rectangle might look like

    **6
    **6
    *66
    

    and my program didn't take in the bottom middle 6 into account.