码迷,mamicode.com
首页 > 其他好文 > 详细

一些神仙题

时间:2019-09-21 22:58:42      阅读:74      评论:0      收藏:0      [点我收藏+]

标签:nod   ++   namespace   ref   stdin   unique   amp   坐标   选择   

灭虫

题目链接
【问题描述】
你需要在一条无限长的道路上喷洒杀虫剂。
在这条道路上,总共有 N 个投放点,其中第 i 个投放点在数轴上坐标 pi 处。在每一
个投放点,你可以选择往左喷洒或往右喷洒。但是由于风向和地理环境的影响,向左喷洒和
向右喷洒的效果不一定相同。具体来说,在一个位置向左喷洒,可以覆盖 [pi - li, pi] 这一段
区域,而向右喷洒可以覆盖 [pi, pi + ri] 这一段区域。
请你决定每个投放点是向左喷洒还是向右喷洒,来使得被杀虫剂覆盖的路段长度和最大。
【输入】
第一行 N。
接下来 N 行,每行 pi, li, ri。
【输出】
输出最大的被杀虫剂覆盖的长度和。

Input Output
4
1 2 2
3 3 3
4 3 3
6 2 2
Output
9

样例说明
让第一个和第三个投放点向左喷洒,其他投放点向右喷洒。
这样能覆盖的区域是 [-1,8],总长度为 9。
【数据说明】
对于测试点 1、 2, N≤ 15;
对于测试点 3、 4, N≤ 3,000, ri = 0;
对于测试点 5、 6, N≤ 30;
对于测试点 7、 8, N≤ 300;
对于测试点 9、 10, N≤ 3,000;
保证 pi, li, ri ≤ 10^9。
Code

#include<bits/stdc++.h>
using namespace std;
const int N = 3010, inf = 1e9 + 7;
int n;
struct node {
    int p, l, r;
    bool operator < (const node &z) const {
        return p < z.p;
    }
} a[N];
int b[N * 3], tot, f[N][N * 3], id[N * 3];
int main() {
    //freopen("kill.in", "r", stdin);
    //freopen("kill.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d", &a[i].p, &a[i].l, &a[i].r);
        a[i].l = a[i].p - a[i].l; a[i].r = a[i].p + a[i].r;
        b[++tot] = a[i].p; b[++tot] = a[i].l; b[++tot] = a[i].r;
    }
    sort(b + 1, b + 1 + tot); tot = unique(b + 1, b + 1 + tot) - b - 1;
    sort(a + 1, a + 1 + n);
    for (int i = 1; i <= n; i++) {
        a[i].p = lower_bound(b + 1, b + 1 + tot, a[i].p) - b;
        a[i].l = lower_bound(b + 1, b + 1 + tot, a[i].l) - b;
        a[i].r = lower_bound(b + 1, b + 1 + tot, a[i].r) - b;
        id[a[i].p] = i;
    }
    //f[i][j]表示前i个区间,贡献最右点小于等于j
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= tot; j++) f[i][j] = f[i - 1][j];
        for (int j = a[i].l + 1; j <= a[i].p; j++) 
            f[i][j] = max(f[i][j], f[i][j - 1] + b[j] - b[j - 1]);
        //i区间贡献(k,j]
        int mx = f[i - 1][a[i].p];
        for (int j = a[i].p + 1; j <= a[i].r; j++) {
            f[i][j] = max(f[i][j], mx + b[j] - b[a[i].p]);
            //i区间贡献(a[i].p,j]
            if (id[j] && a[id[j]].l < a[i].p) mx = max(mx, f[i - 1][a[id[j]].l] + b[a[i].p] - b[a[id[j]].l]);
            //相交
        }
        for (int j = 2; j <= tot; j++) f[i][j] = max(f[i][j], f[i][j - 1]);
    }
    printf("%d\n", f[n][tot]);
    return 0;
} 

一些神仙题

标签:nod   ++   namespace   ref   stdin   unique   amp   坐标   选择   

原文地址:https://www.cnblogs.com/zzy2005/p/11565225.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!