POJ 2376 Cleaning Shifts
枫林晚
2018-03-28 20:47:31
题意:
给定若干子区间,以及目标区间,用最少的子区间覆盖目标区间。若无法实现,输出-1;
思路:
因为每取一个,花费都是1,所以可以使用贪心。(否则要用DP)子区间按照左端点由小到大排序,记录已被覆盖区间,每次找到左端点在[1~r+1]中的右端点的最大值,用有这个最大值的子区间参与覆盖。ans++;
若中途断档,或者循环n之后没有覆盖完[1~r],则输出-1;
证明:
输出-1的做法易证。至于可以成立的情况,那么必然每个格子都要染色,从左边开始,若[1~r]已经被染色,因为已排序,所以之后的区间左端点递增,若左端点>r+1,则此时必须要用一个区间染色了。所以必然要尽可能往右里染色。
代码:
```cpp
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<iostream>
using namespace std;
const int N=25000+5;
int ans;
int n,t;
struct node{
int l,r;
}cow[N];
bool cmp(node a,node b)
{
return a.l<b.l;
}
int L,R;
int main()
{
scanf("%d%d",&n,&t);
L=1;
R=0;
int x,y;
bool flag=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
cow[i].l=x;cow[i].r=y;
}
sort(cow+1,cow+n+1,cmp);
for(int i=1;i<=n;i++)
{
int mx=R;
if(R>=t) break;
while((cow[i].l<=R+1)&&i<=n)
{
mx=max(mx,cow[i].r);
i++;
}
if(mx==R){
flag=1;break;
}
R=mx;
ans++;
if(R>=t) break;
i--;
}
if(R<t) flag=1;//注意
if(flag) printf("-1\n");
else printf("%d\n",ans);
return 0;
}
```
WA之处:关于输出-1的判断,有断档、不足两处需要注意。未考虑到“不足”的情况。