区间覆盖:给定区间,和n的线段,要求选择最少的线段使给定区间完全覆盖。
做法:贪心,先根据左端点从小到大排序,先确定一个答案区间,然后在没有选择的线段中选择一个左端点在答案区间中,右端点最大的加入答案区间。
模板题,但这题是整数覆盖,所以有一个地方不同,具体见代码。
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 25010;
int n,t;
struct stu
{
int l,r;
} s[N];
bool cmp(stu q,stu e)
{
if(q.l != e.l)
return q.l < e.l;
else return q.r > e.r;
}
int main()
{
cin>>n>>t;
for(int i = 0; i < n; i ++ )
cin>>s[i].l>>s[i].r;
int st = 1,en = t;
sort(s,s + n,cmp);//按第一个从小到大排序
int res = 0;
bool flag = false;
for(int i = 0; i < n; i ++ )
{
int j = i,maxx = 0;//j枚举左端点可以覆盖过去的点,maxx取他们右端点最大值
while(j < n && s[j].l <= st)
{
maxx = max(maxx,s[j].r);
j ++ ;
}
if(maxx < st)//最大值都没有覆盖到
break;
res ++ ;
if(maxx >= en)//最大值大于终点
{
flag = true;
break;
}
st = maxx + 1;//和线段的区间不一样的地方,点不带两点之间的线段
//如果是线段不需要加一
i = j - 1;
}
if(flag)
cout<<res;
else
cout<<-1;
return 0;
}
实数区间覆盖模板,但这题有点麻烦,首先是很多数都需要取 double,然后由于是用圆去覆盖一个矩形,所以需要将圆与矩阵的两个交点求出来,分别为他能覆盖的区间的左右端点。
#include<bits/stdc++.h>
using namespace std;
const int N = 10010;
struct stu
{
double l,r;
}s[N];
bool cmp(stu q,stu e)
{
return q.l < e.l;
}
int n;
double l,w;
int main()
{
ios::sync_with_stdio(false);
while(cin>>n>>l>>w)
{
int cnt = 0;//很重要!!!!在这wa了十几次!!
for(int i = 0; i < n; i ++ )
{
double x,d;//用double
cin>>x>>d;
if(d > w / 2)//如果没有交点,不能把两个0,0放进去
{
s[cnt].l = x - (double)sqrt(1.0*d*d-1.0*w*w/4);
s[cnt].r = x + (double)sqrt(1.0*d*d-1.0*w*w/4);
cnt ++;
}
}
sort(s,s + cnt,cmp);//数据的数量是cnt不是n!!
bool flag = false;
int res = 0;
double st = 0,en = l;
if(s[0].l > 0)
cout<<"-1"<<endl;
else
{
for(int i = 0; i < cnt; i ++ )
{
int j = i;
double maxx = -1;
while(j < cnt && s[j].l <= st)
{
maxx = max(maxx,s[j].r);
j ++ ;
}
if(maxx < st)
break;
res ++;
if(maxx >= en)
{
flag = true;
break;
}
st = maxx;//实数不用加一
i = j - 1;
}
if(flag)
cout<<res<<endl;
else
cout<<"-1"<<endl;
}
}
return 0;
}
用 dfs 求出每个靠湖城市能够到的沙漠城市的区间,这里能到的沙漠城市一定是一个连续的区间,具体证明可看 证明 简单易懂,然后就转化成整数区间覆盖模板了。
#include<bits/stdc++.h>
using namespace std;
const int N = 510;
struct stu
{
int l,r;
}s[N];
bool cmp(stu q,stu e)
{
return q.l < e.l;
}
int n,m,res,g[N][N],l[N][N],r[N][N],v[N][N];
int dx[4] = {-1,0,0,1};
int dy[4] = {0,-1,1,0};
void dfs(int x,int y)
{
v[x][y] = 1;
for(int i = 0; i < 4; i ++ )
{
int nx = x + dx[i];
int ny = y + dy[i];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && g[nx][ny] < g[x][y])
{
if(!v[nx][ny])
dfs(nx,ny);
l[x][y] = min(l[x][y],l[nx][ny]);
r[x][y] = max(r[x][y],r[nx][ny]);
}
}
}
int main()
{
cin>>n>>m;
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
cin>>g[i][j];
memset(l,0x3f,sizeof(l));//这个初始化初始化很关键
for(int j = 1; j <= m; j ++ )
l[n][j] = r[n][j] = j;
for(int j = 1; j <= m; j ++ )
dfs(1,j);
for(int j = 1; j <= m; j ++ )
if(!v[n][j])
res ++ ;
if(res)
cout<<0<<endl<<res;
else
{
cout<<1<<endl;
for(int j = 1; j <= m; j ++ )
{
s[j].l = l[1][j];
s[j].r = r[1][j];
}
sort(s + 1,s + m + 1,cmp);
int st = 1,en = m;
for(int i = 1; i <= m; i ++ )
{
int j = i,maxx = 0;
while(j <= m && s[j].l <= st)
{
maxx = max(maxx,s[j].r);
j ++ ;
}
res ++ ;
if(maxx >= en)
break;
st = maxx + 1;
i = j - 1;
}
cout<<res;
}
return 0;
}
这篇博客探讨了区间覆盖问题的解决策略,通过贪心算法实现整数和实数区间覆盖。首先介绍了如何处理整数区间覆盖,然后详细阐述了实数区间覆盖,特别是面对圆覆盖矩形的特殊情况。最后,通过一个实际问题展示了如何将区间覆盖转化为整数区间覆盖模板,并应用到城市与沙漠城市的连通性分析中。

1870

被折叠的 条评论
为什么被折叠?



