HihoCoder 跑马圈地

原题链接 http://hihocoder.com/problemset/problem/1042

问题:在一个m*n的矩形中,圈出一块最大周长为L的连续区域,满足区域面积尽可能大,同时区域边界不能落入内部特定的矩形内。

分析:

1)当周长固定时,围成正方形覆盖的面积最大;

2)考虑到矩形的对称性,内部矩形位置 (阴影区域) 可表示为如下图所示形式,即满足:s1 >= s3 且 s1 >= s2 且 s3 >= s4:

 

3)除非为了避开阴影区域,否则圈出的区域不需内凹;且圈出区域不会半包裹阴影区域,如下图(1)所示:

4)当L足够长时,圈出区域全部包含阴影区域可获得更大的面积,如下图所示:

其中,上图中场景(1)显而易见,而场景(2)也是存在的,例如如下输入:

9 15 40
5 12 4 5

正确输出应该是92,而如果输出69,hihoCoder也会AC,应该是平台的测试集有问题。

规则如下:

1)不包含阴影区域,优先圈A1区域,然后圈A2区域,得到S1

2)包含阴影区域,得到S2

3)取S1和S2中较大的值

 代码如下:

 1 def solve():
 2     n, m, L = (int(x) for x in raw_input().split())
 3     l, r, t, b = (int(x) for x in raw_input().split())
 4     max_hor = max(l, m - r)
 5     max_ver = max(t, n - b)
 6     # 规范化:使阴影区域位于矩形右下方,且Left >= Top
 7     ret = do_solve(m, n, L, max_hor, max_ver, r - l, b - t) if max_hor >= max_ver else \
 8         do_solve(n, m, L, max_ver, max_hor, b - t, r - l)
 9     print(ret)
10 
11 
12 def do_solve(w0, h0, L, l, t, w, h):
13     # 计算包含阴影区域时,所能圈住的最大面积 s1
14     s1 = calc_max_with_block(w0, h0, L, w, h) if w >= h else \
15         calc_max_with_block(h0, w0, L, h, w)
16     if L >= 2 * (h0 + l + w):
17         return s1
18     else:
19         # 计算不包含阴影区域时,所能圈住的最大面积 s2
20         s2 = calc_max_area(l, h0, L)
21         if L > 2 * (h0 + l):
22             w1 = L // 2 - l - h0
23             s2 += w1 * t
24         return max(s1, s2)
25 
26 
27 def calc_max_area(w0, h0, L):
28     w = h = min(w0, h0, L // 4)
29     L -= 2 * (w + h)
30     if L <= 1:
31         return w * h
32     if w0 - w > 0:
33         w += min(w0 - w, L // 2)
34     elif h0 - h > 0:
35         h += min(h0 - h, L // 2)
36     return w * h
37 
38 
39 def calc_max_with_block(w0, h0, L, w, h):
40     L -= 2 * (w + h)
41     if L <= 1:
42         return 0
43     w1 = w
44     h1 = h
45     delta = min(w - h, h0 - h, L // 2)
46     h += delta
47     L -= 2 * delta
48     if L <= 1:
49         return w * h - w1 * h1
50     delta = min(w0 - w, h0 - h, L // 4)
51     w += delta
52     h += delta
53     L -= 4 * delta
54     if L <= 1:
55         return w * h - w1 * h1
56     if w0 - w > 0:
57         w += min(w0 - w, L // 2)
58     elif h0 - h > 0:
59         h += min(h0 - h, L // 2)
60     return w * h - w1 * h1
61 
62 
63 solve()

 

posted on 2020-03-08 10:24  游不动の鱼  阅读(172)  评论(0编辑  收藏  举报