[CodeForces498A]Crazy Town[几何][附简略证明]

题目链接:[CodeForces498A]Crazy Town[几何][附简略证明]

题意分析:n条直线将地图切成多个块,起点终点都在块上,问从起点到终点,最少要走多少步?(有公共边的块认为是相邻的块)

解题思路:猜想:A、B两点间的线段与多少条直线相交,就是我们需要走的步数。即:步数 = 与线段相交的直线条数(直接搜题解的朋友,建议看到这里就自己去实现一方,或者自己去证明下)

简略证明:

首先,交点在线段以外的话,相当于把整个地图的边界变小了,对步数没有影响。

其次,考虑交点在线段上,其中最简单的一种情况(1):

这时中间两条直线将其划分为三个域。

接着我们移动一下直线,有(2):


注意到,当两条线相交后,相当于原来在上面的a线,变成了下面的b线,两条线的切割位置互换了,对于整个最小距离是没有影响的。所以只用考虑交点数即可判断最小步数了。过线段的直线的相交,平行是不影响最终结果的。

证毕。

个人感受:上个学期遇到的题,一点思路都没有。昨天又见到,就大胆猜想了下。说到与AB线段的交点,我昨天第一次是直接求出交点,然后判断有多少个交点在A、B的坐标域内。结果WA36,23333。然后经舍友提醒,原来还有线性规划这档子事,唉呀呀~

具体代码如下:

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <map>
#include <set>
#include <algorithm>
typedef long long ll;
using namespace std;

const double eps = 1e-7;

int main() {
    double x1, x2, y1, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    int ans = 0;
    int n; cin >> n;
    for (int i = 0; i < n; ++i)
    {
        double a, b, c;
        cin >> a >> b >> c;
        if ((a * x1 + b * y1 + c)*(a * x2 + b * y2 + c) < eps) //线性规划:当两点在直线两端时,带入两点,乘积必定是负数
            ++ans;
    }
    cout << ans << '\n';
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值