The first thing that irks me with the code is the use of input. This is evil incarnate, bring equivalent to eval(raw_input()). You should use int(raw_input()) instead.
Your circles can be generated with a list comprehension. I suggest you do so.
You should move things out of the global scope, even if you just put it in a main function. You get free speed improvements out of it and it's easier to refactor.
Your loop is very straightforward, which is good, but there isn't a real need for the second if; we could just calculate the start and ends:
for circle in circles:
for x_rel in range(-circle[2], circle[2]+1):
i = x_rel + circle[0]
# A circle on the origin is bounded on x² + y² = r²
# Solving for y, we have x = ± √(r² - x²)
y_bound = int((circle[2] ** 2 - x_rel ** 2) ** 0.5)
for y_rel in range(-y_bound, y_bound+1):
j = y_rel + circle[1]
if mat[i][j]<=1:
mat[i][j]+=1
if mat[i][j]>1:
ans+=1
The last if section would look nicer as:
mat[i][j] += 1
if mat[i][j] == 2:
ans += 1
or even
mat[i][j] += 1
ans += mat[i][j] == 2
You should consider unpacking the circle in the outer loop:
for center_x, center_y, radius in circles:
This gives:
def main():
n = int(raw_input())
circles = [map(int, raw_input().split()) for _ in range(n)]
mat = [[0 for i in range(1005)] for i in range(1005)]
ans = 0
for center_x, center_y, radius in circles:
for x_rel in range(-radius, radius+1):
i = x_rel + center_x
# A circle on the origin is bounded on x² + y² = r²
# Solving for y, we have x = ± √(r² - x²)
y_bound = int((radius ** 2 - x_rel ** 2) ** 0.5)
for j in range(center_y-y_bound, center_y+y_bound+1):
mat[i][j] += 1
ans += mat[i][j] == 2
print ans
main()
Here's an idea for how to improve the algorithm.
Your code is O(size of grid + total area of circles). Using a dictionary instead of a list of lists would reduce that to O(total area of circles).
My algorithm is instead approximately O(total perimeter of circles · log number of circles) where n is the number of circles. This comes from building something similar to an interval tree for each column:
drawing trees stored as
_______
| ... | 1(..)3 [(1, +1), (3, -1)]
|. . | 0(..)4 [(0, +1), (4, -1)]
|. ... | 0(...3(..)4..)5 [(0, +1), (3, +1), (4, -1), (5, -1)]
|. . . .| 0(...2(..)4..)6 [(0, +1), (2, +1), (4, -1), (6, -1)]
| ... .| 1(...2(..)3..)6 [(1, +1), (2, +1), (3, -1), (6, -1)]
| . .| 2(..)6 [(2, +1), (6, -1)]
| ... | 3(..)5 [(3, +1), (5, -1)]
-------
Instead of storing the whole grid, each row is stores where each circle starts (()and where they end ()).
If you have many tiny circles, the original method could be better. If you have even somewhat large circles this should be faster.
# encoding: utf8
from collections import defaultdict, namedtuple
from math import ceil, floor
Circle = namedtuple("Circle", ["x", "y", "r"])
def read_circle():
x, y, r = raw_input().split()
return Circle(int(x), int(y), int(r))
def project_circles(circles):
columns = defaultdict(list)
for circle in circles:
for x_rel in range(-circle.r, circle.r+1):
# A circle on the origin is bounded on x² + y² = r²
# Solving for y, we have x = ± √(r² - x²)
y_rel = (circle.r ** 2 - x_rel ** 2) ** 0.5
columns[circle.x + x_rel].append((circle.y - y_rel, +1))
columns[circle.x + x_rel].append((circle.y + y_rel, -1))
return columns
def extract_overlaps(column):
# Keep deltas in order, because 0-width slices
# should still count if they cover an integer
column = sorted(column, key=lambda pos_delta: (pos_delta[0], -pos_delta[1]))
num_active = 0
for position, delta in column:
if num_active == 1 and delta == 1:
start = position
if num_active == 2 and delta == -1:
# Yield the number of dots (integers) between them, inclusive
yield int(floor(position)) - int(ceil(start)) + 1
num_active += delta
def main():
circles = [read_circle() for _ in range(int(raw_input()))]
columns = project_circles(circles)
overlaps = (sum(extract_overlaps(column)) for column in columns.values())
print(sum(overlaps))
main()
project_circles builds the tree-like structure and extract_overlaps finds the areas with an overlap of at least 2.
Unfortunately this is much more complex.