给C++新手的USACO 2018 December Silver题解

本文分享了作者在USACO2018银级竞赛中,使用二分查找、优先队列和深度优先搜索解决Convention、ConventionII和MooyoMooyo三道问题的解题思路和代码实现,强调了基础算法和数据结构在竞赛中的重要性。
摘要由CSDN通过智能技术生成

作为即将冲击金级的选手,在这里分享一下自己练习过程中的代码~

目标是尽量用简单的算法和语言来完成和讲解这三道题o(* ̄▽ ̄*)o


USACO 2018 December Contest, Silver Problem 1. Convention

先看题吧:

原题戳这里~

(这题有官方中文翻译喔)

解题:

看到这题我是直接蒙了,这东西咋算啊?w(゚Д゚)w

随后一想,银级题看不出来咋算的多半是用二分查找来遍历某个值⊙▽⊙

所以我定睛一看,直接用二分来判断所有等待时间是否可行并找出最小的那一个不就行了嘛。

这么想的话,有一个设定的等待时间的情况下,求出这个时间可不可行还是很简单的o(^▽^)o

无非就是遍历所有的牛,并判断下一头牛能不能挤进当前车辆,或者时间差距是否过大╰( ̄▽ ̄)╭

 三二一,上代码!

#include <bits/stdc++.h>
using namespace std;

int n, m, c;
vector<int> arrivals;

bool validate(int k){
    int bus_number = 1;
    int ealiest_cow = 0;
    int current_cow = 0;

    while (current_cow < n){
        if ((arrivals[current_cow] - arrivals[ealiest_cow]) > k){
            ealiest_cow = current_cow;
            bus_number ++;
        }

        else if (current_cow - ealiest_cow + 1 > c){
            ealiest_cow = current_cow;
            bus_number ++;
        }

        else{
            current_cow++;
        }

    }

    return bus_number <= m;
    
}


int main(){
    freopen("convention.in", "r", stdin);
	freopen("convention.out", "w", stdout);

    cin >> n >> m >> c;
    arrivals.resize(n);
    for (int i=0; i<n; i++){ cin >> arrivals[i]; }

    sort(arrivals.begin(), arrivals.end());

    int lb = 0;
    int hb = arrivals[n-1] - arrivals[0];
    while (lb < hb){
        int mb = lb + ((hb-lb) / 2);
        // cout << mb << endl;
        if (validate(mb)){
            hb = mb;
        }
        else{
            lb = mb+1;
        }
    }

    cout << lb << endl;
}


补充一点,二分之前记得排序哦o( ̄ε ̄*)


USACO 2018 December Contest, Silver Problem 2. Convention II

同样的,先看题:

原题戳这里~

(这题也有官方中文翻译喔)

解题~:

一看这道题,我就想起了一位故人╰( ̄▽ ̄)╭

这位故人,有着用特定顺序不断把元素放到顶上的能力O(≧口≦)O

Introducing...

priority_queue

!!!

我们优先队列简直是为了这题量身定制的ヾ(´∀`o)+

这道题不就是需要不断地把东西放在最上面嘛!

所以我们需要两个优先队列,分别按照时间和资历存储奶牛n(*≧▽≦*)n

没有同时间到达的,就丢进资历队列里当下一个

有同时间到达的,一起丢进资历队列里就能自动按资历一个个输出啦( ╯▽╰)

然后不断更新最久等待时间就可以辣

代码~启动~

#include <bits/stdc++.h>
using namespace std;

int main(){
    freopen("convention2.in", "r", stdin);
	freopen("convention2.out", "w", stdout);

    int n, T, next;
    int ans = 0;
    cin >> n;

    vector<int> timeArrive(n);
    vector<int> timeEat(n);
    priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > timeOrder;
    priority_queue<int, vector<int>, greater<int> > seniorityOrder;

    for (int i=0; i<n; i++){
        cin >> timeArrive[i] >> timeEat[i];
        timeOrder.push(make_pair(timeArrive[i],i));
    }

    while (!timeOrder.empty() || !seniorityOrder.empty()){
        if (seniorityOrder.empty()){
            T = timeOrder.top().first;
            while(!timeOrder.empty() && timeOrder.top().first<=T){
                seniorityOrder.push(timeOrder.top().second);
                timeOrder.pop();
            }
        }

        next = seniorityOrder.top();
        seniorityOrder.pop();
        ans = max(ans, T-timeArrive[next]);
        T = T + timeEat[next];

        while(!timeOrder.empty() && timeOrder.top().first<=T){
            seniorityOrder.push(timeOrder.top().second);
            timeOrder.pop();
        }
    }
    cout << ans << endl;
}

 USACO 2018 December Contest, Silver Problem 3. Mooyo Mooyo

先看题罢!

原题戳这里~

(没错,这题也有官方中文翻译)

解题:

豁,一上来这个开心消消乐给我看笑了(*^▽^*)

这种判断联通分量的我们熟啊,这不深度优先搜索

这到底想法本身不是很难,但是写起来比较复杂(;′⌒`)

首先得有个while循环,只要当循环内棋盘发生改变就得再执行改变

还得有一个部分负责下落的处理

还得有一个部分负责清除棋盘上的联通部分

再别说还有个DFS呢(;´д`)ゞ

每一个部分出一点错误都运行不了(>﹏<)

所以写这种题的时候记得即使调试哈( ̄o ̄) . z Z

考验基本功的时候到了!把代码端上来吧!

#include <bits/stdc++.h>
using namespace std;

int n, k;
vector<vector<int>> grid;
set<pair<int, int>> seen_set;
set<pair<int, int>> clear_set;
vector<pair<int, int>> clear_vec;
set<pair<int, int>> region_clear_set;

void gridClear(){
    clear_vec.assign(clear_set.begin(), clear_set.end());

    for(vector<pair<int, int>>::iterator it = clear_vec.begin(); it!=clear_vec.end(); it++){
        pair<int, int> x = *it;
        grid[x.first][x.second] = 0;
    }
}

void gravity(){
    vector<int> one_col;
    for (int li=0; li<10; li++){
        for (int co=n-1; co>=0; co--){
			if (grid[co][li] != 0){
				one_col.push_back(grid[co][li]);
				grid[co][li] = 0;
			}
        }
        int col = n-1;
        for(vector<int>::iterator it = one_col.begin(); it!=one_col.end(); it++){
            grid[col][li] = *it;
            col--;
        }
		one_col.clear();
    }
    
}

void dfs(pair<int, int> coord){
    region_clear_set.insert(make_pair(coord.first, coord.second));
    seen_set.insert(make_pair(coord.first, coord.second));
    if (coord.first < n-1){
        if (grid[coord.first+1][coord.second] == grid[coord.first][coord.second] && !region_clear_set.count(make_pair(coord.first+1, coord.second))){
            dfs(make_pair(coord.first+1, coord.second));
        }
    }
    if (coord.first > 0){
        if (grid[coord.first-1][coord.second] == grid[coord.first][coord.second] && !region_clear_set.count(make_pair(coord.first-1, coord.second))){
            dfs(make_pair(coord.first-1, coord.second));
        }
    }
    if (coord.second < 9){
        if (grid[coord.first][coord.second+1] == grid[coord.first][coord.second] && !region_clear_set.count(make_pair(coord.first, coord.second+1))){
            dfs(make_pair(coord.first, coord.second+1));
        }
    }
    if (coord.second > 0){
        if (grid[coord.first][coord.second-1] == grid[coord.first][coord.second] && !region_clear_set.count(make_pair(coord.first, coord.second-1))){
            dfs(make_pair(coord.first, coord.second-1));
        }
    }

    else{
        return;
    }

}

int main(){
    freopen("mooyomooyo.in", "r", stdin);
	freopen("mooyomooyo.out", "w", stdout);

    cin >> n >> k;
    grid.resize(n);
    bool flag = false;
    string s;

    for (int i = 0; i < n; i++){
		cin >> s;
        grid[i].resize(10);
		for (int j = 0; j < 10; j++){
            grid[i][j] = (s[j] - '0');
            
        }
	}

    while (1){
        flag = false;
        seen_set.clear();
        for (int li=0; li<n; li++){
            for (int co=0; co<10; co++){
                region_clear_set.clear();
                if (!seen_set.count(make_pair(li, co)) && grid[li][co] != 0){
                    dfs(make_pair(li, co));    
                }
                if (region_clear_set.size() >= k){
                    clear_set.insert(region_clear_set.begin(), region_clear_set.end());
                    flag = true;
                }
            }
        }
        gridClear();
        clear_set.clear();
        gravity();
        if (flag == false){
            break;
        }

    }
    for (int li=0; li<n; li++){
        for (int co=0; co<10; co++){
               cout << grid[li][co];
        }
        cout << endl;
    }
}

116行啊,你知道我这个116行怎么调试出来的嘛!

题目本身不难的,但是我稀碎的基本功让这个变成了地狱难度(* ̄▽ ̄)( ̄▽:;.…::;

犯的错误包括但不限于:

存储有顺序的数据时用set

dfs忘记加边界判断

...

ヾ( ̄▽ ̄)Bye~Bye~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值