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;
}
二维前缀和模版题。由于坐标的范围是固定的,所以可以根据固定的坐标范围进行二维前缀和求取在边长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;
}