hihoCoder#1042 跑马圈地

原题地址

 

经网友jokeren提醒,后面给出的代码虽然可以AC原题,但存在bug,主要是在矩形覆盖情况的判断上处理的不够完全。

 

看似挺复杂的,但是仔细分析一下可以化简:

首先,不用枚举周长,因为更长的周长总是能够围成更大的面积,所以只要考虑如何在周长为L的前提下枚举面积就行了。

下图中,用蓝色线框表示跑马的路线,灰色矩形表示臭水塘。

假设可以穿越臭水塘,那么:圈地面积=蓝矩形面积 - 蓝矩形内部的灰色矩形面积。

现在不让穿越臭水塘,为了维持面积不变,就需要绕着臭水塘走:

注意:绕路以后,面积不变。

上面这个例子说明:不管你怎么跑马,圈出什么形状的地,都可以转化成一个蓝矩形和黑矩形覆盖的情况(当然如果二者不相交就更简单了)。

所以,不用去考虑圈地的形状,只需要枚举蓝矩形面积,然后减掉臭水塘的面积,就是圈地的面积。

 

上面的转化看上去很美好,但问题来了,虽然面积不变,但周长可能会变化。仔细分析,一共有这几种情况:

情况I:绕路以后,周长不变:

情况II:绕路以后,周长增加:

情况III:绕路以后,周长变小:

情况IV:矩形不相交,无变化:

情况V:蓝矩形覆盖灰矩形,无变化:

情况VI:这种情况是不合法的,遇到就直接跳过吧:

 

 

情况I、IV、V最好,直接计算即可

情况II不考虑,因为周长爆了,不满足周长等于L的条件

情况III也不考虑,因为当计算两个矩形不相交的时候会覆盖到这种情景。

所以,只需要考虑情况I、IV、V即可,是不是瞬间变简单了!

 

那如何判断是情况I、IV、V呢?

仔细观察,可以发现矩形的重叠情况跟灰矩形在蓝矩形内部的点的数量有关:

如果灰矩形在蓝矩形内部的顶点数分别对应了上面的几种情况。需要注意的是,顶点数为0实际上对应情况V和情况VI,但因为情况VI是非法的,所以这里需要额外判断一下。

 

代码:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int n, m, L;
 6 int l, r, t, b;
 7 
 8 int run_horse(int pl, int pr, int pt, int pb) {
 9   int ll = max(l, pl);
10   int rr = min(r, pr);
11   int tt = max(t, pt);
12   int bb = min(b, pb);
13 
14   if (ll >= rr || tt >= bb)
15     return (pr - pl) * (pb - pt);
16 
17   int inside = 0;
18   if (ll > pl && ll < pr && tt > pt && tt < pb)
19     inside++;
20   if (rr > pl && rr < pr && tt > pt && tt < pb)
21     inside++;
22   if (ll > pl && ll < pr && bb > pt && bb < pb)
23     inside++;
24   if (rr > pl && rr < pr && bb > pt && bb < pb)
25     inside++;
26 
27   if (inside == 1 || inside == 4)
28     return (pr - pl) * (pb - pt) - (rr - ll) * (bb - tt);
29   else
30     return 0;
31 }
32 
33 int main() {
34   int res = 0;
35 
36   cin >> n >> m >> L;
37   cin >> l >> r >> t >> b;
38 
39   for (int i = 0; i < n; i++) {
40     for (int j = 0; j < m; j++) {
41       int w = 1;
42       int h = (L - 2 * w) / 2;
43       while (w > 0 && h > 0) {
44         res = max(res, run_horse(j, min(m, j + w), i, min(n, i + h)));
45         w++;
46         h = (L - 2 * w) / 2;
47       }
48     }
49   }
50 
51   cout << res << endl;
52 }

 

转载于:https://www.cnblogs.com/boring09/p/4368198.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值