QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#526371#5898. Havannah320x2000 2184ms575208kbPython34.6kb2024-08-21 14:30:502024-08-21 14:30:50

Judging History

你现在查看的是最新测评结果

  • [2024-08-21 14:30:50]
  • 评测
  • 测评结果:0
  • 用时:2184ms
  • 内存:575208kb
  • [2024-08-21 14:30:50]
  • 提交

answer

from sys import stdin

DELTAS = [(+1, +1), (0, +1), (-1, 0), (-1, -1), (0, -1), (+1, 0)]
CORNER_MASK = 0b10101010101
SIDE_MASK = CORNER_MASK << 1

class Board:
    def __init__(self, S):
        self.S = S
        self.D = S * 2 - 1
        self.rep = [[None] * self.D for _ in range(self.D)]

    def which_corner_or_side(self, x, y):
        corner = (0  if x == self.D and y == self.D else
                  2  if x == self.S and y == self.D else
                  4  if x ==      1 and y == self.S else
                  6  if x ==      1 and y ==      1 else
                  8  if x == self.S and y ==      1 else
                  10 if x == self.D and y == self.S else
                  None)
        if corner is not None:
            return 1 << corner
        side = (1  if y == self.D and x >= self.S else
                3  if x + self.S - 1 == y else
                5  if x == 1 and y <= self.S else
                7  if y == 1 and x <= self.S else
                9  if y + self.S - 1 == x else
                11 if x == self.D and y >= self.S else
                None)
        if side is not None:
            return 1 << side
        return None
    
    def dist_to_center(self, x, y):
        dx, dy = x - self.S, y - self.S
        return max(dx, dy, 0) - min(dx, dy, 0)
        
    def mark(self, x, y):
        assert self.rep[x - 1][y - 1] is None
        corner_or_side = self.which_corner_or_side(x, y)
        self.rep[x - 1][y - 1] = corner_or_side if corner_or_side is not None else (x, y)
        return self.rep[x - 1][y - 1]
    
    def is_onboard(self, x, y):
        return 1 <= x <= self.D and 1 <= y <= self.D and abs(x - y) < self.S
    
    def has_parent(self, x, y):
        self_rep = self.rep[x - 1][y - 1]
        return self_rep is not None and not isinstance(self_rep, int) and self_rep != (x, y)
            
    def find(self, x, y):
        if not self.is_onboard(x, y):
            return None
        if not self.has_parent(x, y):
            return self.rep[x - 1][y - 1]
        self.rep[x - 1][y - 1] = self.find(*self.rep[x - 1][y - 1])
        return self.rep[x - 1][y - 1]
    
    def propagate(self, x, y, rep_value):
        while True:
            old_rep_value = self.rep[x - 1][y - 1]
            self.rep[x - 1][y - 1] = rep_value
            if self.has_parent(x, y):
                x, y = old_rep_value
            else:
                break
        
    def union(self, x1, y1, x2, y2):
        rep1 = self.find(x1, y1)
        assert rep1 is not None
        rep2 = self.find(x2, y2)
        assert rep2 is not None
        if isinstance(rep1, int):
            merged = rep1 | rep2 if isinstance(rep2, int) else rep1
        else:
            merged = rep2 if isinstance(rep2, int) else (rep1 if self.dist_to_center(*rep1) >= self.dist_to_center(*rep2) else rep2)
        if rep1 != merged:
            self.propagate(x1, y1, merged)
        if rep2 != merged:
            self.propagate(x2, y2, merged)
        
if __name__ == "__main__":
    T = int(stdin.readline())
    for t in range(T):
        S, M = map(int, stdin.readline().split())
        board = Board(S)
        result = ""
        for k in range(M):
            x, y = map(int, stdin.readline().split())
            if result:
                continue
            if board.find(x, y) is not None:
                continue
            wins = []
            neigh_reps = []
            dx, dy = DELTAS[-1]
            last_neigh_rep = board.find(x + dx, y + dy)
            for dx, dy in DELTAS:
                neigh_rep = board.find(x + dx, y + dy)
                if last_neigh_rep is None and neigh_rep is not None:
                    neigh_reps.append(neigh_rep)
                last_neigh_rep = neigh_rep
            if len(neigh_reps) > 1 and any(i for i in range(len(neigh_reps)) if neigh_reps[i-1] == neigh_reps[i]):
                wins.append("ring")
            self_rep = board.mark(x, y)
            for dx, dy in DELTAS:
                nx, ny = x + dx, y + dy
                if board.find(nx, ny) is None:
                    continue
                board.union(x, y, nx, ny)
            self_rep = board.find(x, y)
            if isinstance(self_rep, int):
                if (self_rep & CORNER_MASK).bit_count() >= 2:
                    wins.append("bridge")
                if (self_rep & SIDE_MASK).bit_count() >= 3:
                    wins.append("fork")
            if wins:
                wins.sort()
                result =f"{'-'.join(wins)} in move {k + 1}"
        if not result:
            result = "none"
        print(f"Case #{t + 1}: {result}")

Details

Tip: Click on the bar to expand more detailed information

Subtask #1:

score: 0
Wrong Answer

Test #1:

score: 0
Wrong Answer
time: 108ms
memory: 11100kb

input:

200
49 99
13 45
37 85
4 3
9 3
47 1
39 1
97 71
31 2
37 1
48 3
4 2
47 2
16 1
6 3
70 27
38 2
13 56
39 3
23 21
45 17
38 1
10 3
13 8
13 2
19 2
7 1
2 2
21 3
13 3
15 1
40 61
6 1
45 1
45 3
15 59
5 3
26 1
78 72
51 78
46 1
35 2
29 2
37 2
43 3
8 2
12 2
16 3
29 3
46 2
16 2
30 3
5 2
12 3
15 25
10 1
19 3
49 1
66 ...

output:

Case #1: ring in move 21
Case #2: ring in move 39
Case #3: none
Case #4: ring in move 59
Case #5: none
Case #6: ring in move 42
Case #7: none
Case #8: ring in move 40
Case #9: none
Case #10: none
Case #11: none
Case #12: none
Case #13: ring in move 54
Case #14: ring in move 61
Case #15: ring in move...

result:

wrong answer 1st lines differ - expected: 'Case #1: ring in move 88', found: 'Case #1: ring in move 21'

Subtask #2:

score: 0
Wrong Answer

Test #2:

score: 0
Wrong Answer
time: 2184ms
memory: 575208kb

input:

20
3000 1799
2800 3000
2800 2800
3000 2800
3200 3000
3200 3200
3000 3200
2800 2999
2801 2800
3001 2801
3200 3001
3199 3200
2999 3199
2800 2998
2802 2800
3002 2802
3200 3002
3198 3200
2998 3198
2800 2997
2803 2800
3003 2803
3200 3003
3197 3200
2997 3197
2800 2996
2804 2800
3004 2804
3200 3004
3196 32...

output:

Case #1: ring in move 1799
Case #2: bridge in move 9
Case #3: none
Case #4: ring in move 1799
Case #5: fork in move 9
Case #6: bridge-fork-ring in move 15
Case #7: none
Case #8: ring in move 1799
Case #9: none
Case #10: bridge-fork in move 5
Case #11: bridge in move 2
Case #12: ring in move 6
Case #...

result:

wrong answer 2nd lines differ - expected: 'Case #2: bridge-ring in move 9', found: 'Case #2: bridge in move 9'