您的位置:首页 > 其它

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

2015-07-03 08:28 141 查看
题目链接:[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: