InternBootcamp/internbootcamp/bootcamp/daliceandthedoll/daliceandthedoll.py
2025-05-23 15:27:15 +08:00

384 lines
13 KiB
Python
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""#
### 谜题描述
Alice got a new doll these days. It can even walk!
Alice has built a maze for the doll and wants to test it. The maze is a grid with n rows and m columns. There are k obstacles, the i-th of them is on the cell (x_i, y_i), which means the cell in the intersection of the x_i-th row and the y_i-th column.
However, the doll is clumsy in some ways. It can only walk straight or turn right at most once in the same cell (including the start cell). It cannot get into a cell with an obstacle or get out of the maze.
More formally, there exist 4 directions, in which the doll can look:
1. The doll looks in the direction along the row from the first cell to the last. While moving looking in this direction the doll will move from the cell (x, y) into the cell (x, y + 1);
2. The doll looks in the direction along the column from the first cell to the last. While moving looking in this direction the doll will move from the cell (x, y) into the cell (x + 1, y);
3. The doll looks in the direction along the row from the last cell to first. While moving looking in this direction the doll will move from the cell (x, y) into the cell (x, y - 1);
4. The doll looks in the direction along the column from the last cell to the first. While moving looking in this direction the doll will move from the cell (x, y) into the cell (x - 1, y).
.
Standing in some cell the doll can move into the cell in the direction it looks or it can turn right once. Turning right once, the doll switches it's direction by the following rules: 1 → 2, 2 → 3, 3 → 4, 4 → 1. Standing in one cell, the doll can make at most one turn right.
Now Alice is controlling the doll's moves. She puts the doll in of the cell (1, 1) (the upper-left cell of the maze). Initially, the doll looks to the direction 1, so along the row from the first cell to the last. She wants to let the doll walk across all the cells without obstacles exactly once and end in any place. Can it be achieved?
Input
The first line contains three integers n, m and k, separated by spaces (1 ≤ n,m ≤ 10^5, 0 ≤ k ≤ 10^5) — the size of the maze and the number of obstacles.
Next k lines describes the obstacles, the i-th line contains two integer numbers x_i and y_i, separated by spaces (1 ≤ x_i ≤ n,1 ≤ y_i ≤ m), which describes the position of the i-th obstacle.
It is guaranteed that no two obstacles are in the same cell and no obstacle is in cell (1, 1).
Output
Print 'Yes' (without quotes) if the doll can walk across all the cells without obstacles exactly once by the rules, described in the statement.
If it is impossible to walk across the maze by these rules print 'No' (without quotes).
Examples
Input
3 3 2
2 2
2 1
Output
Yes
Input
3 3 2
3 1
2 2
Output
No
Input
3 3 8
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Output
Yes
Note
Here is the picture of maze described in the first example:
<image>
In the first example, the doll can walk in this way:
* The doll is in the cell (1, 1), looks to the direction 1. Move straight;
* The doll is in the cell (1, 2), looks to the direction 1. Move straight;
* The doll is in the cell (1, 3), looks to the direction 1. Turn right;
* The doll is in the cell (1, 3), looks to the direction 2. Move straight;
* The doll is in the cell (2, 3), looks to the direction 2. Move straight;
* The doll is in the cell (3, 3), looks to the direction 2. Turn right;
* The doll is in the cell (3, 3), looks to the direction 3. Move straight;
* The doll is in the cell (3, 2), looks to the direction 3. Move straight;
* The doll is in the cell (3, 1), looks to the direction 3. The goal is achieved, all cells of the maze without obstacles passed exactly once.
Here is a reference code to solve this task. You can use this to help you genereate cases or validate the solution.
```python
from __future__ import division, print_function
def main():
n,m,k=map(int,input().split())
obstacles_x=[[-1,m] for _ in range(n)]
obstacles_y=[[-1,n] for _ in range(m)]
for i in range(k):
x,y=map(int,input().split())
obstacles_x[x-1].append(y-1)
obstacles_y[y-1].append(x-1)
for item in obstacles_x:
item.sort()
for item in obstacles_y:
item.sort()
flag=1
traversed=0
turn=1
curr_x=0
curr_y=-1
import bisect
lower_x=0
upper_x=n
lower_y=-1
upper_y=m
while flag==1:
flag=0
if turn==1:
idx=bisect.bisect_right(obstacles_x[curr_x],curr_y)
if min(upper_y-1,obstacles_x[curr_x][idx]-1)>curr_y:
traversed+=(min(upper_y-1,obstacles_x[curr_x][idx]-1)-curr_y)
flag=1
turn=2
curr_y=min(upper_y-1,obstacles_x[curr_x][idx]-1)
upper_y=curr_y
elif turn==2:
idx=bisect.bisect_right(obstacles_y[curr_y],curr_x)
if min(upper_x-1,obstacles_y[curr_y][idx]-1)>curr_x:
traversed+=min(upper_x-1,obstacles_y[curr_y][idx]-1)-curr_x
flag=1
turn=3
curr_x=min(upper_x-1,obstacles_y[curr_y][idx]-1)
upper_x=curr_x
elif turn==3:
idx=bisect.bisect_right(obstacles_x[curr_x],curr_y)
idx-=1
if max(lower_y+1,obstacles_x[curr_x][idx]+1)<curr_y:
traversed-=max(lower_y+1,obstacles_x[curr_x][idx]+1)-curr_y
flag=1
turn=4
curr_y=max(lower_y+1,obstacles_x[curr_x][idx]+1)
lower_y=curr_y
else :
idx=bisect.bisect_left(obstacles_y[curr_y],curr_x)
idx-=1
if max(lower_x+1,obstacles_y[curr_y][idx]+1)<curr_x:
traversed-=max(lower_x+1,obstacles_y[curr_y][idx]+1)-curr_x
flag=1
turn=1
curr_x=max(lower_x+1,obstacles_y[curr_y][idx]+1)
lower_x=curr_x
if traversed==n*m-k:
print(\"Yes\")
else :
print(\"No\")
######## Python 2 and 3 footer by Pajenegod and c1729
# Note because cf runs old PyPy3 version which doesn't have the sped up
# unicode strings, PyPy3 strings will many times be slower than pypy2.
# There is a way to get around this by using binary strings in PyPy3
# but its syntax is different which makes it kind of a mess to use.
# So on cf, use PyPy2 for best string performance.
py2 = round(0.5)
if py2:
from future_builtins import ascii, filter, hex, map, oct, zip
range = xrange
import os, sys
from io import IOBase, BytesIO
BUFSIZE = 8192
class FastIO(BytesIO):
newlines = 0
def __init__(self, file):
self._file = file
self._fd = file.fileno()
self.writable = \"x\" in file.mode or \"w\" in file.mode
self.write = super(FastIO, self).write if self.writable else None
def _fill(self):
s = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
self.seek((self.tell(), self.seek(0,2), super(FastIO, self).write(s))[0])
return s
def read(self):
while self._fill(): pass
return super(FastIO,self).read()
def readline(self):
while self.newlines == 0:
s = self._fill(); self.newlines = s.count(b\"\n\") + (not s)
self.newlines -= 1
return super(FastIO, self).readline()
def flush(self):
if self.writable:
os.write(self._fd, self.getvalue())
self.truncate(0), self.seek(0)
class IOWrapper(IOBase):
def __init__(self, file):
self.buffer = FastIO(file)
self.flush = self.buffer.flush
self.writable = self.buffer.writable
if py2:
self.write = self.buffer.write
self.read = self.buffer.read
self.readline = self.buffer.readline
else:
self.write = lambda s:self.buffer.write(s.encode('ascii'))
self.read = lambda:self.buffer.read().decode('ascii')
self.readline = lambda:self.buffer.readline().decode('ascii')
sys.stdin, sys.stdout = IOWrapper(sys.stdin), IOWrapper(sys.stdout)
input = lambda: sys.stdin.readline().rstrip('\r\n')
# Cout implemented in Python
import sys
class ostream:
def __lshift__(self,a):
sys.stdout.write(str(a))
return self
cout = ostream()
endl = '\n'
# Read all remaining integers in stdin, type is given by optional argument, this is fast
def readnumbers(zero = 0):
conv = ord if py2 else lambda x:x
A = []; numb = zero; sign = 1; i = 0; s = sys.stdin.buffer.read()
try:
while True:
if s[i] >= b'0' [0]:
numb = 10 * numb + conv(s[i]) - 48
elif s[i] == b'-' [0]: sign = -1
elif s[i] != b'\r' [0]:
A.append(sign*numb)
numb = zero; sign = 1
i += 1
except:pass
if s and s[-1] >= b'0' [0]:
A.append(sign*numb)
return A
if __name__== \"__main__\":
main()
```
请完成上述谜题的训练场环境类实现,包括所有必要的方法。
"""
from bootcamp import Basebootcamp
import random
import bisect
from bootcamp import Basebootcamp
def solve(n, m, obstacles):
if n == 0 or m == 0:
return "No"
obstacles_x = [[-1, m] for _ in range(n)]
obstacles_y = [[-1, n] for _ in range(m)]
for x, y in obstacles:
x0 = x - 1
y0 = y - 1
bisect.insort(obstacles_x[x0], y0)
bisect.insort(obstacles_y[y0], x0)
for row in obstacles_x:
row.sort()
for col in obstacles_y:
col.sort()
flag = 1
traversed = 0
turn = 1
curr_x, curr_y = 0, -1
lower_x, upper_x = 0, n
lower_y, upper_y = -1, m
while flag == 1:
flag = 0
if turn == 1:
idx = bisect.bisect_right(obstacles_x[curr_x], curr_y)
next_y = min(upper_y-1, obstacles_x[curr_x][idx]-1)
if next_y > curr_y:
traversed += next_y - curr_y
flag = 1
turn = 2
curr_y, upper_y = next_y, next_y
elif turn == 2:
idx = bisect.bisect_right(obstacles_y[curr_y], curr_x)
next_x = min(upper_x-1, obstacles_y[curr_y][idx]-1)
if next_x > curr_x:
traversed += next_x - curr_x
flag = 1
turn = 3
curr_x, upper_x = next_x, next_x
elif turn == 3:
idx = bisect.bisect_right(obstacles_x[curr_x], curr_y) - 1
next_y = max(lower_y+1, obstacles_x[curr_x][idx]+1)
if next_y < curr_y:
traversed += curr_y - next_y
flag = 1
turn = 4
curr_y, lower_y = next_y, next_y
else:
idx = bisect.bisect_left(obstacles_y[curr_y], curr_x) - 1
next_x = max(lower_x+1, obstacles_y[curr_y][idx]+1)
if next_x < curr_x:
traversed += curr_x - next_x
flag = 1
turn = 1
curr_x, lower_x = next_x, next_x
total_cells = n * m - len(obstacles)
return "Yes" if traversed == total_cells else "No"
class Daliceandthedollbootcamp(Basebootcamp):
def __init__(self, min_n=1, max_n=5, min_m=1, max_m=5):
self.min_n = min_n
self.max_n = max_n
self.min_m = min_m
self.max_m = max_m
def case_generator(self):
n = random.randint(self.min_n, self.max_n)
m = random.randint(self.min_m, self.max_m)
max_k = n*m -1
k = random.randint(0, max_k) if max_k > 0 else 0
available = [(x,y) for x in range(1,n+1) for y in range(1,m+1) if (x,y) != (1,1)]
obstacles = random.sample(available, k) if k else []
return {
'n': n,
'm': m,
'k': k,
'obstacles': obstacles
}
@staticmethod
def prompt_func(case):
input_str = f"{case['n']} {case['m']} {case['k']}"
for x,y in case['obstacles']:
input_str += f"\n{x} {y}"
return f"""Alice的玩偶走迷宫问题。迷宫大小为{case['n']}行×{case['m']}列,有{case['k']}个障碍物。玩偶从(1,1)出发,初始向右,每次可直行或原地右转一次。要求遍历所有无障碍格且不重复。是否可行?
输入格式:
{input_str}
请分析路径可能性,并用[answer]标签包裹答案Yes/No"""
@staticmethod
def extract_output(output):
import re
matches = re.findall(r'\[answer\]\s*(Yes|No)\s*\[/answer\]', output, re.IGNORECASE)
return matches[-1].capitalize() if matches else None
@classmethod
def _verify_correction(cls, sol, case):
correct = solve(case['n'], case['m'], case['obstacles'])
return sol.lower() == correct.lower()