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

250 lines
8.6 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.

"""#
### 谜题描述
After years of hard work scientists invented an absolutely new e-reader display. The new display has a larger resolution, consumes less energy and its production is cheaper. And besides, one can bend it. The only inconvenience is highly unusual management. For that very reason the developers decided to leave the e-readers' software to programmers.
The display is represented by n × n square of pixels, each of which can be either black or white. The display rows are numbered with integers from 1 to n upside down, the columns are numbered with integers from 1 to n from the left to the right. The display can perform commands like \"x, y\". When a traditional display fulfills such command, it simply inverts a color of (x, y), where x is the row number and y is the column number. But in our new display every pixel that belongs to at least one of the segments (x, x) - (x, y) and (y, y) - (x, y) (both ends of both segments are included) inverts a color.
For example, if initially a display 5 × 5 in size is absolutely white, then the sequence of commands (1, 4), (3, 5), (5, 1), (3, 3) leads to the following changes:
<image>
You are an e-reader software programmer and you should calculate minimal number of commands needed to display the picture. You can regard all display pixels as initially white.
Input
The first line contains number n (1 ≤ n ≤ 2000).
Next n lines contain n characters each: the description of the picture that needs to be shown. \"0\" represents the white color and \"1\" represents the black color.
Output
Print one integer z — the least number of commands needed to display the picture.
Examples
Input
5
01110
10010
10001
10011
11110
Output
4
Here is a reference code to solve this task. You can use this to help you genereate cases or validate the solution.
```python
#include <bits/stdc++.h>
using namespace std;
int n, i, j, a[2001][2001], b[2001][2001], ans, J, C, A[2001][2001],
B[2001][2001];
char c[2001][2001];
int main() {
cin >> n;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++) cin >> c[i][j];
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));
ans = 0;
for (J = n; J >= 2; J--) {
i = 1;
j = J;
for (C = 1; C <= n + 1 - J; C++) {
if (c[i][j] == '0' && (a[i][j] + b[i][j]) % 2 == 1 ||
c[i][j] == '1' && (a[i][j] + b[i][j]) % 2 == 0) {
ans++;
a[i][j - 1] = a[i][j] + 1;
b[i + 1][j] = b[i][j] + 1;
} else {
a[i][j - 1] = a[i][j];
b[i + 1][j] = b[i][j];
}
i++;
j++;
}
i = n;
j = n + 1 - J;
for (C = 1; C <= n + 1 - J; C++) {
if (c[i][j] == '0' && (A[i][j] + B[i][j]) % 2 == 1 ||
c[i][j] == '1' && (A[i][j] + B[i][j]) % 2 == 0) {
ans++;
A[i][j + 1] = A[i][j] + 1;
B[i - 1][j] = B[i][j] + 1;
} else {
A[i][j + 1] = A[i][j];
B[i - 1][j] = B[i][j];
}
i--;
j--;
}
}
for (i = 1; i <= n; i++) {
if (c[i][i] == '0' && (a[i][i] + b[i][i] + A[i][i] + B[i][i]) % 2 == 1 ||
c[i][i] == '1' && (a[i][i] + b[i][i] + A[i][i] + B[i][i]) % 2 == 0)
ans++;
}
cout << ans << endl;
}
```
请完成上述谜题的训练场环境类实现,包括所有必要的方法。
"""
from bootcamp import Basebootcamp
import random
import re
from typing import List
from bootcamp import Basebootcamp
class Cereaderdisplaybootcamp(Basebootcamp):
def __init__(self, n=5):
super().__init__()
self.n = n # 确保n的范围符合题目要求
if not 1 <= n <= 2000:
raise ValueError("n must be between 1 and 2000")
def case_generator(self):
"""逆向生成有效案例:先生成命令模式再推导目标图像"""
n = self.n
# 生成随机命令集合(保证可逆性)
commands = self.generate_valid_commands(n)
# 生成目标网格
grid = self.simulate_commands(n, commands)
return {
'n': n,
'grid': [''.join(map(str, row)) for row in grid],
'correct_answer': len(commands)
}
def generate_valid_commands(self, n: int) -> List[tuple]:
"""基于参考算法逻辑生成最小命令集合"""
# 根据题目参考算法逆向生成命令
commands = []
# 随机选择对角线操作概率
if random.random() < 0.3:
diag_count = random.randint(0, n)
commands += [(i+1, i+1) for i in random.sample(range(n), diag_count)]
# 随机生成非对角线操作
non_diag = [(i+1, j+1) for i in range(n) for j in range(n) if i != j]
commands += random.sample(non_diag, k=random.randint(0, len(non_diag)))
return list(set(commands)) # 去重后返回
def simulate_commands(self, n: int, commands: List[tuple]) -> List[List[int]]:
"""精确模拟命令作用效果"""
grid = [[0]*n for _ in range(n)]
for x, y in commands:
# 处理行x的区域
start_col = min(x, y) - 1
end_col = max(x, y) - 1
for col in range(start_col, end_col + 1):
if 0 <= col < n:
grid[x-1][col] ^= 1
# 处理列y的区域
start_row = min(x, y) - 1
end_row = max(x, y) - 1
for row in range(start_row, end_row + 1):
if 0 <= row < n:
grid[row][y-1] ^= 1
return grid
@staticmethod
def prompt_func(question_case) -> str:
n = question_case['n']
grid = "\n".join(question_case['grid'])
return f"""您需要为新型电子阅读器计算最小操作命令数。显示屏规格:{n}x{n},初始全白。目标图案:
{grid}
每条命令(x,y)会翻转:
1. 第x行从第min(x,y)列到第max(x,y)列
2. 第y列从第min(x,y)行到第max(x,y)行
请给出所需的最小命令数量,并置于[answer][/answer]标签内。"""
@staticmethod
def extract_output(output: str) -> int:
# 增强型匹配模式,处理可能存在的换行符
matches = re.findall(r'\[answer\s*\]\s*(\d+)\s*\[/\s*answer\s*\]', output, re.IGNORECASE)
if matches:
try:
return int(matches[-1].strip())
except:
return None
return None
@classmethod
def _verify_correction(cls, solution, identity):
# 双重验证机制
try:
# 方法1预存答案验证
if solution == identity['correct_answer']:
return True
# 方法2实时计算验证防止逆向生成错误
n = identity['n']
grid = [[int(c) for c in row] for row in identity['grid']]
calculated = cls.calculate_min_commands(n, grid)
return solution == calculated
except:
return False
@staticmethod
def calculate_min_commands(n: int, grid: List[List[int]]) -> int:
"""完整实现参考算法"""
a = [[0]*(n+2) for _ in range(n+2)]
b = [[0]*(n+2) for _ in range(n+2)]
A = [[0]*(n+2) for _ in range(n+2)]
B = [[0]*(n+2) for _ in range(n+2)]
ans = 0
# 处理右上三角区域
for J in range(n, 1, -1):
i, j = 1, J
for _ in range(n - J + 1):
current_value = grid[i-1][j-1]
total = (a[i][j] + b[i][j]) % 2
if (current_value == 0 and total == 1) or (current_value == 1 and total == 0):
ans += 1
a[i][j-1] = a[i][j] + 1
b[i+1][j] = b[i][j] + 1
else:
a[i][j-1] = a[i][j]
b[i+1][j] = b[i][j]
i += 1
j += 1
# 处理左下三角区域
for J in range(2, n+1):
i, j = n, J
for _ in range(n - J + 1):
current_value = grid[i-1][j-1]
total = (A[i][j] + B[i][j]) % 2
if (current_value == 0 and total == 1) or (current_value == 1 and total == 0):
ans += 1
A[i][j+1] = A[i][j] + 1
B[i-1][j] = B[i][j] + 1
else:
A[i][j+1] = A[i][j]
B[i-1][j] = B[i][j]
i -= 1
j -= 1
# 处理对角线元素
for i in range(1, n+1):
current_value = grid[i-1][i-1]
total = (a[i][i] + b[i][i] + A[i][i] + B[i][i]) % 2
if (current_value == 0 and total == 1) or (current_value == 1 and total == 0):
ans += 1
return ans