您的位置:首页 > 其它

10382 - Watering Grass(贪心 区间覆盖问题)洒水面覆盖

2014-05-22 18:07 591 查看
double qiuzhi(int id)
{
    double t1=cc[id].rid*cc[id].rid;
    double t2=w*w/4;
    double t3=t1-t2;
    double t4=sqrt(t3);
    return t4;
}

void to_qujian()
{
    for(int i=0; i<t; i++)
    {
        double zhi=qiuzhi(i);
        qq[i].a=cc[i].pos-zhi;
        qq[i].b=cc[i].pos+zhi;
    }
}


典型的贪心区间覆盖问题,刘汝佳书上有讲,只有思路没有代码~他总是这么令人蛋疼。。

对本题来说,关键的一点在于由具体问题向“区间”的抽象~!用圆与矩形边的交点作为区间的左右端点!

用了两种方法,按书上的方法,采取多次截取合适区间的方法做了一遍,代码比较清晰实现出来了,但是超时。

原因已经分析清楚,本以为是0(n)的复杂度,但是忽略了排序的n log(n)的复杂度,每次循环都排序,10000的数据量超时是意料之中的事情。

#include<cstdio>//这是超时的代码~看清楚了~~
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=10000+10;
int n,t;
double l,w;
int flag1,flag2;

struct circle
{
double pos;
double rid;
} cc[maxn];
struct qujian
{
double a;
double b;
} qq[maxn];
void input(int n,double l,double w)
{
t=0;
int temp=n;
for(int i=0; i<temp; i++)
{
double a1,b1;
scanf("%lf%lf",&a1,&b1);
if(b1<=w/2)
{
n--;
continue;
}
else
{
cc[t].pos=a1;
cc[t++].rid=b1;
}
}
}

bool cut_qujian(double left,double right)
{
flag1=0;
flag2=0;
for(int i=0; i<t; i++)
{
if(qq[i].a<=left)
{
flag1=1;
qq[i].a=left;
}
if(qq[i].b>=right-0.0000000001)
{
flag2=1;
qq[i].b=right;
}
}
if(flag1==1&&flag2==1)
return true;
else
return false;
}
double qiuzhi(int id) { double t1=cc[id].rid*cc[id].rid; double t2=w*w/4; double t3=t1-t2; double t4=sqrt(t3); return t4; } void to_qujian() { for(int i=0; i<t; i++) { double zhi=qiuzhi(i); qq[i].a=cc[i].pos-zhi; qq[i].b=cc[i].pos+zhi; } }

int cmp(qujian a,qujian b)
{
if(a.a!=b.a) return a.a<b.a;
else return a.b>b.b;
}

int main()
{
while(scanf("%d%lf%lf",&n,&l,&w)!=EOF)
{
input(n,l,w);
to_qujian();
double left=0,right=l;
int ans=-1;
int cnt=0;
while(cut_qujian(left,right))
{
cnt++;
sort(qq,qq+t,cmp);
left=qq[0].b;
if(left>=right)
{
ans=1;
break;
}
}
if(ans==-1)
{
printf("-1\n");
}
else
printf("%d\n",cnt);
}
return 0;
}


然后思路肯定是不能换,就换实现的方式好了~

用了下面这种看似0(n^2),但实际上复杂度为0(n)的方法,学长给的,觉得很好。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=10000+10;
int n,t;
double l,w;
int flag1,flag2;

struct circle
{
double pos;
double rid;
} cc[maxn];
struct qujian
{
double a;
double b;
} qq[maxn];
void input(int n,double l,double w)
{
t=0;
int temp=n;
for(int i=0; i<temp; i++)
{
double a1,b1;
scanf("%lf%lf",&a1,&b1);
if(b1<=w/2)
{
n--;
continue;
}
else
{
cc[t].pos=a1;
cc[t++].rid=b1;
}
}
}
double qiuzhi(int id) { double t1=cc[id].rid*cc[id].rid; double t2=w*w/4; double t3=t1-t2; double t4=sqrt(t3); return t4; } void to_qujian() { for(int i=0; i<t; i++) { double zhi=qiuzhi(i); qq[i].a=cc[i].pos-zhi; qq[i].b=cc[i].pos+zhi; } }

int cmp(qujian a,qujian b)
{
return a.a<b.a;
}

int solve()
{
int cnt=0;
double right=0;
for(int i=0; i<t; i++)
{

double nowr=right;
for(; qq[i].a<=right; i++)
{
if(qq[i].b>nowr)
nowr=qq[i].b;
}
if(nowr==right) return -1;
right=nowr;
cnt++;
i--;
}
if(right<l) return -1;
return cnt;
}
int main()
{
while(scanf("%d%lf%lf",&n,&l,&w)!=EOF)
{
input(n,l,w);
to_qujian();
int ans;
sort(qq,qq+t,cmp);
ans=solve();
if(ans==-1)
{
printf("-1\n");
}
else
printf("%d\n",ans);
}
return 0;
}


好久都没能有像做这道题目的感受了,感觉很好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: