AcWing 防晒
Description
有C头奶牛进行日光浴,第i头奶牛需要minSPF[i]到maxSPF[i]单位强度之间的阳光。
每头奶牛在日光浴前必须涂防晒霜,防晒霜有L种,涂上第i种之后,身体接收到的阳光强度就会稳定为SPF[i],第i种防晒霜有cover[i]瓶。
求最多可以满足多少头奶牛进行日光浴。
Input
第一行输入整数C和L。
接下来的C行,按次序每行输入一头牛的minSPF和maxSPF值,即第i行输入minSPF[i]和maxSPF[i]。
再接下来的L行,按次序每行输入一种防晒霜的SPF和cover值,即第i行输入SPF[i]和cover[i]。
每行的数据之间用空格隔开。
Output
- 输出一个整数,代表最多可以满足奶牛日光浴的奶牛数目。
Data Size
- 1≤C,L≤2500,
1≤minSPF≤maxSPF≤1000,
1≤SPF≤1000
Sample Input
3 2 3 10 2 5 1 5 6 2 4 1
Sample Output
2
题解:
- 贪心。
- 首先这道题可以想到二分图匹配吧。把奶牛看做一个集合,防晒霜看做一个集合,用匈牙利求最大匹配。理论上是可行的。但是匈牙利的复杂度是O(nm),n是2500可以接受,但是对于此题m可能有很大很大啊(因为一种防晒霜可以有多瓶)。所以考虑换算法。
- 贪心?怎么想到的?
- 按照maxSPF递增的顺序排序,依次考虑每头奶牛。
- 对于每头奶牛,在她能用的防晒霜里选SPF最小的用。为什么?用“微扰法”证明:对于当前奶牛能用的防晒霜x, y,那么后面一头奶牛会出现3种情况
- x, y她也都可以用
- x, y她都不能用
- x她用不了,但y她可以用
- 可以看出,不管哪一种情况,给当前奶牛用x都是最优的。所以这是一个正确的贪心策略。复杂度是O(nm),在这里m就变成了定值。因为用了cnt来计数。
- 可以用二分优化成O(nlogn),我就懒没写了。
- 可能二分图我写的常数巨大,导致过不了。还请大大们帮看看是哪里还可以优化。
//贪心
#include
#include
#include
#define N 2505
using namespace std;
struct B {int val, cnt;} b[N];
struct A {int x, y;} a[N];
int n, m, ans;
bool cmp1(A u, A v) {return u.y < v.y;}
bool cmp2(B u, B v) {return u.val < v.val;}
int main()
{
freopen("A110.in", "r", stdin);
freopen("A110.out", "w", stdout);
cin >> n >> m;
for(int i = 1; i <= n; i++) scanf("%d%d", &a[i].x, &a[i].y);
for(int i = 1; i <= m; i++) scanf("%d%d", &b[i].val, &b[i].cnt);
sort(a + 1, a + 1 + n, cmp1), sort(b + 1,b + 1 + m, cmp2);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(b[j].cnt && a[i].x <= b[j].val && b[j].val <= a[i].y)
{b[j].cnt--, ans++; break;}
cout << ans;
return 0;
}
//二分图
#include
#include
#include
#include
#define N 100005
using namespace std;
struct A {int x, y;} a[N];
int n, m, g, ans;
int mat[N], b[N];
bool vis[N];
bool dfs(int p)
{
for(int i = 1; i <= m; i++)
if(a[p].x <= b[i] && b[i] <= a[p].y && !vis[i])
{
vis[i] = 1;
if(!mat[i] || dfs(mat[i]))
{
mat[i] = p;
return 1;
}
}
return 0;
}
int main()
{
freopen("A110.in", "r", stdin);
freopen("A110.out", "w", stdout);
cin >> n >> m;
for(int i = 1; i <= n; i++) scanf("%d%d", &a[i].x, &a[i].y);
for(int i = 1; i <= m; i++)
{
int val, cnt;
scanf("%d%d", &val, &cnt);
for(int j = 1; j <= cnt; j++) b[++g] = val;
}
m = g;
for(int i = 1; i <= n; i++)
{
memset(vis, 0, sizeof(vis));
if(dfs(i)) ans++;
}
cout << ans;
return 0;
}