牛客OI–种树(贪心策略)
限制:每段路最多种一棵树,
目的: 用最少的树 去 满足每段路的 要求
分析:要求树能够 种的 “价值最大化”
---- 只种一棵树就满足所有需求(理想)
-------一棵树能在多个路段(区间)内
-------------即把树种尽量种在路段(区间)重合部分
如何转换呢?
即 从右向左 衍生
显然,我们给这些个区间排序(以右端点为准)从小到大,,,
需要用到的俩重要变量 记录
******************该区间的树(count) 和 实际种植的树(ans)
然后依次遍历每个区间,区间内=前边重合的+右端种的
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
//
const int N = 3 * 10e4 + 10;
bool road[N];
//
struct section {
int b, e, t;
}sec[5050];
//
bool cmp(section a, section b) {
return a.e <= b.e;
}
//
int main()
{
int n, h;
cin >> n >> h;
for (int i = 0; i < h; ++i) {
cin >> sec[i].b >> sec[i].e >> sec[i].t;
}
//贪心策略:优先重合部分 即 右侧
sort(sec, sec + h, cmp);
int ans = 0;//实际
for (int i = 0; i < h; ++i)
{
int count = 0;//范围内的树
//遍历区间内每一路检查是否有树
for (int j = sec[i].b; j <= sec[i].e; ++j)
{
if (road[j] == 1)
count++;
}
//前边不够数时后边补
if(count<sec[i].t)
for (int j = sec[i].e; j >= sec[i].b; --j)
{//第j路
if (road[j] == 0)
{
road[j] = 1;
count++;
ans++;
}
//一直种到够
if (count == sec[i].t)
break;
}
}
cout << ans << '\n';
return 0;
}
road[] 这个数组 就好比 筛法素数 中 来标记 下标是否是素数
这里用来标记是否种了树;