牛客算法竞赛入门课第一节习题 2020.10.2

USACO 2009 Dec S]Selfish Grazing

贪心思想,按照结束时间排序,然后统计个数即可。

#include <bits/stdc++.h>
using namespace std;
bool cmp(const pair<int,int>& a, const pair<int,int>& b) {
    if(a.second == b.second)
        return a.first < b.first;
    return a.second < b.second;
}
int main() {
    int n;
    cin >> n;
    vector<pair<int,int>> p;
    for(int i = 0; i < n; i++) {
        pair<int, int> k;
        cin >> k.first >> k.second;
        p.emplace_back(k);
    }
    sort(p.begin(), p.end(), cmp);
    int start = p[0].first, end = p[0].second, res = 1;
    for(int i = 1; i < n; i++) {
        if(end <= p[i].first) {
            start = p[i].first;
            end = p[i].second;
            res += 1;
        }
    }
    cout << res << endl;
    return 0;
}

USACO 2006 Ope B]Cows on a Leash

贪心思想,按照结尾排序,每趟记录开始点和结束点,每趟将已切分开的序列进行标记。在序列的头和尾结点切分不能算切分,不能算。

#include <bits/stdc++.h>
using namespace std;
bool cmp(const pair<long long,long long>& a, const pair<long long,long long>& b) {
    if(a.second == b.second)
        return a.first < b.first;
    return a.second < b.second;
}
bool alltrue(vector<bool> vis) {
    for(int i = 0; i < vis.size(); i++) {
        if(!vis[i])
            return false;
    }
    return true;
}
int main() {
    int n;
    cin >> n;
    vector<pair<long long,long long>> p;
    vector<bool> vis(n, false);
    for(int i = 0; i < n; i++) {
        pair<long long, long long> k;
        cin >> k.first >> k.second;
        k.second += k.first;
        p.emplace_back(k);
    }
    sort(p.begin(), p.end(), cmp);
    long long start = 0, end = 0;
    int res = 0;
    while(1) {
        bool flag = false;
        for(int i = 0; i < n; i++) {
            if(!vis[i]) {
                if(!flag) {
                    start = p[i].first;
                    end = p[i].second;
                    flag = true;
                    vis[i] = true;
                    continue;
                }
                //在临界点也无法进行切分开
                if(p[i].second <= start || p[i].first >= end)
                    continue;
                start = max(start, p[i].first);
                end = min(end, p[i].second);
                vis[i] = true;
            }
        }
        res += 1;
        if(alltrue(vis))
            break;
    }
    cout << res << endl;
    return 0;
}

[HNOI2003]激光炸弹

二维前缀和模版题。由于坐标的范围是固定的,所以可以根据固定的坐标范围进行二维前缀和求取在边长R的范围内,能够取到的价值最大值。

#include <bits/stdc++.h>
using namespace std;
long long num[5010][5010] = {0};
int main() {
    memset(num, 0, sizeof(num));
    int n, r;
    cin >> n >> r;
    r = min(r, 5000);
    for(int i = 0; i < n; i++) {
        int x, y, v;
        cin >> x >> y >> v;
        num[x + 1][y + 1] += v;
    }
    //二维前缀和求取
    for(int i = 1; i <= 5001; i++) {
        for(int j = 1; j <= 5001; j++)
            num[i][j] = num[i][j] + num[i - 1][j] + num[i][j - 1] - num[i - 1][j - 1];
    }
    //求取以R为边长的正方形结果
    long long res = 0;
    for(int i = r; i <= 5001; i++) {
        for(int j = r; j <= 5001; j++) {
            long long tmp = num[i][j] - num[i][j - r] - num[i - r][j] + num[i - r][j - r];
            res = max(res, tmp);
        }
    }
    cout << res << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值