結果
| 問題 |
No.180 美しいWhitespace (2)
|
| ユーザー |
|
| 提出日時 | 2015-05-19 18:41:52 |
| 言語 | Python3 (3.13.1 + numpy 2.2.1 + scipy 1.14.1) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,919 bytes |
| コンパイル時間 | 73 ms |
| コンパイル使用メモリ | 12,928 KB |
| 実行使用メモリ | 11,264 KB |
| 最終ジャッジ日時 | 2024-07-06 05:44:04 |
| 合計ジャッジ時間 | 1,915 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 WA * 1 |
| other | AC * 31 |
ソースコード
def convex_hull(points):
'''二次元平面上の点のリスト points の凸包を返す。Andrew のアルゴリズムを使用。
引数:
points = [(x0, y0), (x1, y1),...] 点のリスト
同じ点は含まない(全て異なる点である)とする。
返り値:
convex_hull = [(xi, yi), (xj, yj),...] 点のリスト。時計回りに並んでいる。
'''
points.sort()
upper_bounds = get_bounds(points)
points.reverse()
lower_bounds = get_bounds(points)
del upper_bounds[-1]
del lower_bounds[-1]
upper_bounds.extend(lower_bounds)
return upper_bounds
def get_bounds(points):
bounds = [points[0], points[1]]
for xi, yi in points[2:]:
while len(bounds) > 1 and not is_convex(bounds, xi, yi):
del bounds[-1]
bounds.append((xi, yi))
return bounds
def is_convex(bounds, x2, y2):
x1, y1 = bounds[-1]
x0, y0 = bounds[-2]
return (x1 - x0) * (y2 - y1) < (y1 - y0) * (x2 - x1)
def read_data():
N = int(input())
AB = [tuple(map(int, input().split())) for i in range(N)]
return N, AB
def solve(N, AB):
# 重複する点を除く
AB = list(set(AB))
if len(AB) == 1:
return 1
# 凸包を得る
ps = convex_hull(AB)
ps.reverse() # 反時計回りに並べ直す。
# tab = 1 としたときの最小値と最大値の出現場所にカーソルをおく。
xy = [x + y for x, y in ps]
min_xy = min(xy)
max_xy = max(xy)
min_idx = xy.index(min_xy)
max_idx = xy.index(max_xy)
# 凸包を半時計回りに走査して、 x + tab * y の幅が最小となる tab をさがす。
return find_best_tab_width(ps, min_idx, max_idx)
def find_best_tab_width(ps, min_idx, max_idx):
n = len(ps)
tab = 1.0
min_cost = float('inf')
while tab > 0:
tab_int0 = int(tab)
tab_int1 = tab_int0 + 1
new_cost0 = cost(ps, min_idx, max_idx, tab_int0, n)
new_cost1 = cost(ps, min_idx, max_idx, tab_int1, n)
if new_cost0 < min_cost:
min_cost = new_cost0
best_tab = tab_int0
if new_cost1 < min_cost:
min_cost = new_cost1
best_tab = tab_int1
min_idx, max_idx, tab = get_next(ps, n, min_idx, max_idx, tab)
return best_tab
def cost(ps, min_idx, max_idx, tab, n):
'''計算誤差に対処するため、最小値, 最大値をとるはずのidx の前後についても計算している。
'''
min_idxs = [(min_idx-1) % n, min_idx, (min_idx+1) % n]
min_val = min([ps[i][0] + tab * ps[i][1] for i in min_idxs])
max_idxs = [(max_idx-1) % n, max_idx, (max_idx+1) % n]
max_val = max([ps[i][0] + tab * ps[i][1] for i in max_idxs])
return max_val - min_val
def get_next(ps, n, min_idx, max_idx, tab):
min_x0, min_y0 = ps[min_idx]
min_x1, min_y1 = ps[(min_idx + 1) % n]
max_x0, max_y0 = ps[max_idx]
max_x1, max_y1 = ps[(max_idx + 1) % n]
dx_min, dy_min = min_x1 - min_x0, min_y0 - min_y1
dx_max, dy_max = max_x0 - max_x1, max_y1 - max_y0
tab_min_f = get_slope(dx_min, dy_min)
tab_max_f = get_slope(dx_max, dy_max)
if tab_min_f == 0:
return min_idx, (max_idx + 1) % n, tab_max_f
if tab_max_f == 0:
return (min_idx + 1) % n, max_idx, tab_min_f
if tab_min_f < tab_max_f:
return (min_idx + 1) % n, max_idx, tab_min_f
if tab_max_f < tab_min_f:
return min_idx, (max_idx + 1) % n, tab_max_f
else:
return (min_idx + 1) % n, (max_idx + 1) % n, tab_min_f
def get_slope(dx, dy):
if dx <= 0 or dy <= 0:
return 0
else:
return 1.0 * dx / dy
def checker(tab, AB):
for TAB in [tab - 1, tab, tab + 1]:
xy = [x + TAB * y for x, y in AB]
score = max(xy) - min(xy)
print(score)
if __name__ == '__main__':
N, AB = read_data()
print(solve(N, AB))