作为即将冲击金级的选手,在这里分享一下自己练习过程中的代码~
目标是尽量用简单的算法和语言来完成和讲解这三道题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~