-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathmaximum-number-of-moves-to-kill-all-pawns.py
54 lines (51 loc) · 1.96 KB
/
maximum-number-of-moves-to-kill-all-pawns.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Time: O(p * n^2 + p^2 + p^2 * 2^p) = O(p^2 * 2^p)
# Space: O(p^2 + n^2 + p * 2^p) = O(p * 2^p)
# bfs, bitmasks, dp
class Solution(object):
def maxMoves(self, kx, ky, positions):
"""
:type kx: int
:type ky: int
:type positions: List[List[int]]
:rtype: int
"""
N = 50
DIRECTIONS = ((1, 2), (-1, 2), (1, -2), (-1, -2), (2, 1), (-2, 1), (2, -1), (-2, -1))
POS_INF = float("inf")
NEG_INF = float("-inf")
def popcount(r):
return bin(r)[2:].count('1')
def bfs(r, c):
dist = [[POS_INF]*N for _ in xrange(N)]
dist[r][c] = 0
q = [(r, c)]
while q:
new_q = []
for r, c in q:
for dr, dc in DIRECTIONS:
nr, nc = r+dr, c+dc
if not (0 <= nr < N and 0 <= nc < N and dist[nr][nc] == POS_INF):
continue
dist[nr][nc] = dist[r][c]+1
new_q.append((nr, nc))
q = new_q
return dist
p = len(positions)
positions.append([kx, ky])
dist = [[0]*(p+1) for _ in xrange(p+1)]
for i, (r, c) in enumerate(positions):
d = bfs(r, c)
for j in xrange(i+1, p+1):
dist[j][i] = dist[i][j] = d[positions[j][0]][positions[j][1]]
dp = [[POS_INF if popcount(mask)&1 else NEG_INF]*p for mask in xrange(1<<p)]
dp[-1] = [0]*p
for mask in reversed(xrange(1, 1<<p)):
fn = (max, min)[(popcount(mask)&1)^1]
for i in xrange(p):
if (mask&(1<<i)) == 0:
continue
for j in xrange(p):
if j == i or (mask&(1<<j)) == 0:
continue
dp[mask^(1<<i)][j] = fn(dp[mask^(1<<i)][j], dp[mask][i]+dist[i][j])
return max(dp[1<<i][i]+dist[i][p] for i in xrange(p))