POJ3614
思路1
按照minSPF递减排序,依次考虑每头奶牛
对于每头奶牛,扫描一遍所有的防晒霜,在这头奶牛呢
能用的范围内,并且瓶数还有剩余时候找到最大SPF值使用
每一瓶是否可以被使用,取决于minSPF和maxSPF条件限制
每一个不低于当前奶牛的minSPF的防晒霜,
都不会低于后面一个奶牛的minSPF
对于当前奶牛可以使用的任意两瓶防晒霜x<y
要么xy均可使用(后牛的maxSPF处于xy值上方),
xy均不可使用(后牛的maxSPF处于xy值下方),
如果(后牛的maxSPF处于xy值中间)则x可用,y不可用
所以当前的牛选择y对整体比较好
而且每头牛对整体的贡献都是1,所以放弃使用给后面的
牛使用也不回对整体变的更大
AC1
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define pii pair<int, int>
#define psi pair<string, int>
#define ull unsigned ll
#define pb push_back
#define mp make_pair
#define ld long double
#define X first
#define Y second
const int N = 2555 + 7;
#define INF ~0ULL
int n, m;
pii a[N];
pii b[N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i].first >> a[i].second;
for (int i = 1; i <= m; i++)
cin >> b[i].first >> b[i].second;
sort(a + 1, a + 1 + n, greater<pii>());
sort(b + 1, b + 1 + m, greater<pii>());
int ans = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (a[i].X <= b[j].X && a[i].Y >= b[j].X && b[j].Y)
{
ans++;
b[j].Y--;
break;
}
}
}
cout<<ans<<endl;
return 0;
}
思路2
那么将奶牛按照阳光强度的最小值从小到大排序。
将防晒霜也按照能固定的阳光强度从小到大排序
从小的防晒霜枚举,将所有符合 最小值小于等于该防晒霜的奶牛的最大值放于优先队列中
然后从优先对列中取出较小值比较是否满足maxSPF>=spf
如果牛的最大值小于最小防晒霜就舍弃次牛
AC2
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define pii pair<int, int>
#define psi pair<string, int>
#define ull unsigned ll
#define pb push_back
#define mp make_pair
#define ld long double
#define X first
#define Y second
const int N = 2555 + 7;
#define INF ~0ULL
int n, m;
pii a[N];
pii b[N];
priority_queue<int, vector<int>, greater<int>> q;
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i].first >> a[i].second;
for (int i = 1; i <= m; i++)
cin >> b[i].first >> b[i].second;
sort(a + 1, a + 1 + n);
sort(b + 1, b + 1 + m);
int ans = 0, j = 1;
for (int i = 1; i <= m; i++)
{
while (j <= n && a[j].X <= b[i].X)
{
q.push(a[j].Y);
j++;
}
while (!q.empty() && b[i].Y)
{
int x = q.top();
q.pop();
if (x < b[i].X)
continue;
ans++;
b[i].Y--;
}
}
cout << ans << endl;
//system("pause");
return 0;
}
POJ3190
思路
按照牛开始吃草的时间排序
对于每头牛,如果有空位置就到最到先
离开的那头牛的位置吃草,没有就新开一个
AC
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define pii pair<int, int>
#define psi pair<string, int>
#define ull unsigned ll
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define ld long double
const int N = 5E5 + 7;
#define INF ~0ULL
priority_queue<int, vector<int>, greater<int>> q;
int n;
pii niu[N];
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> niu[i].X >> niu[i].Y;
sort(niu + 1, niu + 1 + n);
q.push(niu[1].Y);
int ans = 1;
for (int i = 2; i <= n; i++)
{
int x = q.top();
q.pop();
if (x <= niu[i].X)
q.push(niu[i].Y);
else
{
ans++;
q.push(x);
q.push(niu[i].Y);
}
}
cout << ans << endl;
}
POJ1328
链接: link.
思路
先将坐标转换成雷达区间,然后就是每个区间至少一个点的最小点数
AC
#include <bits/stdc++.h>
using namespace std;
struct Node
{
double Left, Right;
} s[1010];
bool cmp(Node x, Node y)
{
return x.Left < y.Left;
}
int main()
{
int n, d;
int time = 0;
while (cin >> n >> d && (n != 0 || d != 0)) //这个n d不同时0的条件错了几次,刚开始写成&&了,那样的话是都不能为0。
{
time++;
double x, y;
double l;
int p = 1;//flag
for (int i = 0; i < n; i++)
{
cin >> x >> y;
if (y > d && p)
p = 0;
else //存能覆盖该小岛的圆心所在的区间
l = sqrt(d * d * 1.0 - y * y), s[i].Left = x - l, s[i].Right = x + l;
}
if (p)
{
int sum = 1;
sort(s, s + n, cmp);
double now = s[0].Right;
for (int i = 1; i < n; i++)
{
if (s[i].Left > now)
sum++,
now = s[i].Right;
else if (s[i].Right < now)
now = s[i].Right;
}
cout << "Case " << time << ": " << sum << endl;
}
else
cout << "Case " << time << ": -1" << endl;
}
return 0;
}
NOIP2012/CH0701
链接: link.
POJ2054
思路
错误的贪心:每一步都在可以被染色的点里选择权值最大的染色,
读者很容易构造出其反例,只要构造出一棵树,让一个权值很小的
节点下边很多权值巨大的节点,另一个权值较大的点却没有子节点
从这个错误的贪心中想到,我们可以提取出一个正确的性质,树中
除根节点权值最大的点,一定会在他的父节点被染色后立即染色
于是我们可以确定的是,树中权值最大的点及其父节点的染色操作是
连续进行的,我们可以把这两个点“合并起来”,合并得到的新点的权值
设为这两个点的权值的平均值。
例如:有xyz的三个点,我们已知x和y的染色操作是连续进行的,那么
就有两种可能的染色方案:
1,先x,y再z 代价x+2y+3z
2,先z,再x,y 代价z+2x+3y
同时加上(z-y)
1,x+y+4z
2, 2z+2x+2y
除以二
1,(x+y)/2+2z
2, z+2*((x+y)/2)
这恰好就相当于有权值为(x+y)/2和z的两个点的两种染色次序。换
言之,下一列两种情况的最优染色次序可以互相转化
1,权值为x,y,z的三个点。
2, 权值为(x+y)/2和z的两个点
进一步推近,我们可以得到一种“等效权值”的算法,记录每
个点是由多少点合并而成的,一个点的“等效权值”定义为:
该点包含的原始权值总和/该点包含的原始点数