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

229 lines
5.9 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.

"""#
### 谜题描述
Convexity of a set of points on the plane is the size of the largest subset of points that form a convex polygon. Your task is to build a set of n points with the convexity of exactly m. Your set of points should not contain three points that lie on a straight line.
Input
The single line contains two integers n and m (3 ≤ m ≤ 100, m ≤ n ≤ 2m).
Output
If there is no solution, print \"-1\". Otherwise, print n pairs of integers — the coordinates of points of any set with the convexity of m. The coordinates shouldn't exceed 108 in their absolute value.
Examples
Input
4 3
Output
0 0
3 0
0 3
1 1
Input
6 3
Output
-1
Input
6 6
Output
10 0
-10 0
10 1
9 1
9 -1
0 -2
Input
7 4
Output
176166 6377
709276 539564
654734 174109
910147 434207
790497 366519
606663 21061
859328 886001
Here is a reference code to solve this task. You can use this to help you genereate cases or validate the solution.
```python
n,m=map(int,raw_input().split())
print -1 if 3==m and n>4 else '\n'.join(map(lambda x:'%d %d'%x,[(i,i*i) for i in range(m)]+[(i*i+10001,i) for i in range(n-m)]))
```
请完成上述谜题的训练场环境类实现,包括所有必要的方法。
"""
from bootcamp import Basebootcamp
import re
import random
from bootcamp import Basebootcamp
class Dsetofpointsbootcamp(Basebootcamp):
def __init__(self, m_min=3, m_max=100, max_coordinate=10**8):
super().__init__()
self.m_min = max(m_min, 3) # 确保最小m值符合题目要求
self.m_max = min(m_max, 100)
self.max_coordinate = max_coordinate
def case_generator(self):
while True:
m = random.randint(self.m_min, self.m_max)
max_possible_n = min(2 * m, 100) # 根据题目约束n ≤ 2m
# 生成合法n的范围
if m == 3:
# 允许生成无效案例(n>4)
n = random.choice([
random.randint(3, 4), # 有效案例
random.randint(5, max_possible_n) # 无效案例
])
else:
n = random.randint(m, max_possible_n)
# 确保20%概率生成边界案例
if random.random() < 0.2:
if m == 3:
n = 5 # 强制无效案例
else:
n = 2 * m # 最大边界案例
return {"n": n, "m": m}
@staticmethod
def prompt_func(question_case) -> str:
n = question_case["n"]
m = question_case["m"]
example = ""
if m == 3 and n == 4:
example = "\n例如当n=4, m=3时有效解可能是\n0 0\n3 0\n0 3\n1 1"
elif m == 6 and n == 6:
example = "\n例如当n=6, m=6时有效解可能是\n10 0\n-10 0\n10 1\n9 1\n9 -1\n0 -2"
prompt = f"""## 平面点集凸度构造问题
### 问题描述
给定两个整数n和m需要构造一个包含n个点的集合使得
1. 集合的凸度最大凸多边形顶点数恰好为m
2. 集合中任意三点不共线
3. 所有点坐标绝对值不超过1e8
### 输入参数
- n = {n}
- m = {m}
### 输出要求
{'- 当且仅当m=3且n>4时输出-1' if m ==3 else ''}
- 输出{n}个点的坐标,每行两个整数
- 坐标范围:|x|, |y| ≤ 1e8
{example}
### 答案格式
将答案包裹在[answer]标记中:
[answer]
你的答案
[/answer]"""
return prompt
@staticmethod
def extract_output(output):
# 使用非贪婪匹配查找最后一个答案块
matches = re.findall(r'\[answer\]\s*(.*?)\s*\[/answer\]', output, re.DOTALL)
if not matches:
return None
last_answer = matches[-1].strip()
if last_answer == "-1":
return "-1"
try:
points = [tuple(map(int, line.strip().split())) for line in last_answer.split('\n') if line.strip()]
return points
except:
return None
@classmethod
def _verify_correction(cls, solution, identity):
n, m = identity['n'], identity['m']
# 处理无解情况验证
if solution == "-1":
return m == 3 and n > 4
# 检查基本格式
if not isinstance(solution, list) or len(solution) != n:
return False
# 检查坐标范围和唯一性
seen = set()
for x, y in solution:
if abs(x) > 1e8 or abs(y) > 1e8:
return False
if (x, y) in seen:
return False
seen.add((x, y))
# 检查三点共线
for i in range(n):
for j in range(i+1, n):
for k in range(j+1, n):
a, b, c = solution[i], solution[j], solution[k]
# 计算面积法判断共线
area = (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0])
if area == 0:
return False
# 计算凸包
hull = cls.convex_hull(solution)
return len(hull) == m
@staticmethod
def convex_hull(points):
"""Andrew's monotone chain algorithm"""
points = sorted(set(points))
if len(points) <= 1:
return points
lower = []
for p in points:
while len(lower) >= 2:
a, b = lower[-2], lower[-1]
cross = (b[0] - a[0]) * (p[1] - a[1]) - (b[1] - a[1]) * (p[0] - a[0])
if cross > 0:
break
lower.pop()
lower.append(p)
upper = []
for p in reversed(points):
while len(upper) >= 2:
a, b = upper[-2], upper[-1]
cross = (b[0] - a[0]) * (p[1] - a[1]) - (b[1] - a[1]) * (p[0] - a[0])
if cross > 0:
break
upper.pop()
upper.append(p)
return lower[:-1] + upper[:-1]