UVA10382-Watering Grass(贪心)

题目链接

http://acm.hust.edu.cn/vjudge/problem/21419

题意

给定一个长方形,并且给定一系列圆的圆心p和半径r,要求用最小的圆将长方形覆盖住

思路

区间覆盖问题,关键是怎么转化为区间,因为只需要覆盖住长方形,所以我们可以只考虑长方形和圆相交的部分
这里写图片描述
如图,这样就将圆的覆盖转化成了区间覆盖问题

感觉这题的精度比较神奇,最先加了eps一直WA,后来没有考虑精度竟然直接A掉了,附上两个没加eps和加了eps的AC代码

代码

  1. 无eps
#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <deque>
#include <bitset>
#include <algorithm>
using namespace std;

#define PI acos(-1.0)
#define LL long long
#define PII pair<int, int>
#define PDD pair<double, double>
#define PLL pair<LL, LL>
#define mp make_pair
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "wb", stdout)
#define scan(x) scanf("%d", &x)
#define scan2(x, y) scanf("%d%d", &x, &y)
#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define sqr(x) (x) * (x)
#define pr(x) cout << #x << " = " << x << endl
#define lc o << 1
#define rc o << 1 | 1
#define pl() cout << endl

const int maxn = 10000 + 5;
const int eps = 1e-6;
int n;
double l, w;

bool cmp(PDD x, PDD y) {
    return x.first < y.first;
}

int main() {
    while (~scanf("%d %lf %lf", &n, &l, &w)) {
        vector<PDD> v;
        v.clear();
        double p, r;
        for (int i = 0; i < n; i++) {
            scanf("%lf %lf", &p, &r);
            if (r <= w / 2) continue;
            double x = sqrt(sqr(r) - sqr(w) / 4.0);
            v.push_back(mp(p - x, p + x));
        }
        double st = 0.0, ted = 0.0;
        int tot = 0;
        sort(v.begin(), v.end(), cmp);
        int len = v.size();
        int i = 0;
        while (i < len) {
            if (st >= l) break;
            if (v[i].first > st && st < l) break;
            ted = v[i].second;
            while (i < len && v[i].first <= st) {
                ted = max(ted, v[i].second);
                i++;
            }
            st = ted;
            tot++;
        }
        if (st >= l) printf("%d\n", tot);
        else printf("-1\n");
    }
    return 0;
}
  1. 加上eps
#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <deque>
#include <bitset>
#include <algorithm>
using namespace std;

#define PI acos(-1.0)
#define LL long long
#define PII pair<int, int>
#define PDD pair<double, double>
#define PLL pair<LL, LL>
#define mp make_pair
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "wb", stdout)
#define scan(x) scanf("%d", &x)
#define scan2(x, y) scanf("%d%d", &x, &y)
#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define sqr(x) (x) * (x)
#define pr(x) cout << #x << " = " << x << endl
#define lc o << 1
#define rc o << 1 | 1
#define pl() cout << endl

const int maxn = 10000 + 5;
const int eps = 1e-6;
const int tmp = 0;
int n;
double l, w;

bool cmp(PDD x, PDD y) {
    return x.first < y.first;
}

int main() {
    while (~scanf("%d %lf %lf", &n, &l, &w)) {
        vector<PDD> v;
        v.clear();
        double p, r;
        for (int i = 0; i < n; i++) {
            scanf("%lf %lf", &p, &r);
            if (r <= w / 2) continue;
            double x = sqrt(sqr(r) - sqr(w) / 4.0);
            v.push_back(mp(p - x, p + x));
        }
        double st = 0.0, ted = 0.0;
        int tot = 0;
        sort(v.begin(), v.end(), cmp);
        int len = v.size();
        int i = 0;
        while (i < len) {
            if (st >= l + eps) break;
            if (v[i].first > st + eps && st < l - eps) break;
            ted = v[i].second;
            while (i < len && v[i].first <= st - eps) {
                ted = max(ted, v[i].second);
                i++;
            }
            st = ted;
            tot++;
        }
        if (st >= l + eps) printf("%d\n", tot);
        else printf("-1\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值