有了上道题的基础,这题并不难,,但是一开始TLE了,后来一直WA。。。
TLE是因为二分的时间复杂度还是有点大,但稍微优化一下就卡过了。
先附上TLE的代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAX=1005;
int n;
double dl[MAX][MAX],dh[MAX][MAX];
double wei[MAX][MAX];
struct point
{
int x,y,z;
}p[MAX];
double prim()
{
double dis[MAX];
bool vis[MAX];
memset(vis,false,sizeof(vis));
memset(dis,INF,sizeof(dis));
int k=0;
dis[k]=0;vis[k]=true;
for(int i=1;i<n;i++)
{
for(int j=0;j<n;j++)
if(!vis[j]&&dis[j]>wei[k][j])
dis[j]=wei[k][j];
int mi=INF;
for(int j=0;j<n;j++)
if(!vis[j]&&dis[j]<mi)
{
mi=dis[j];
k=j;
}
vis[k]=true;
}
double ans=0;
for(int i=0;i<n;i++)
ans+=dis[i];
return ans;
}
bool judge(double mid)
{
memset(wei,INF,sizeof(wei));
for(int i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
wei[i][j]=wei[j][i]=dh[i][j]-mid*dl[i][j];
}
}
double ans=prim();
if(ans<=0)//mid偏大
return true;
else
return false;
}
int main()
{
while(~scanf("%d",&n))
{
if(n==0)
break;
for(int i=0;i<n;i++)
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
memset(dl,INF,sizeof(dl));
memset(dh,INF,sizeof(dh));
for(int i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
dl[i][j]=dl[j][i]=sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
dh[i][j]=dh[j][i]=fabs(p[i].z-p[j].z);
}
}
double l=0,r=10000000;
while(r-l>1e-6)
{
double mid=(l+r)/2;
if(judge(mid))
r=mid;
else
l=mid;
}
printf("%.3f\n",l);
}
return 0;
}
后来发现上界r是可以变小一些的,然后再优化一些部分,终于AC了。。
需要注意dis数组在更新的时候,要把mid值利用进去,不然会出错。附上AC代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAX=1005;
int n;
double dl[MAX][MAX],dh[MAX][MAX];
double wei[MAX][MAX];
struct point
{
double x,y,z;
}p[MAX];
double prim(double mid)
{
double dis[MAX];
bool vis[MAX];
double ans=0;
memset(vis,false,sizeof(vis));
int k=0;
vis[k]=true;
for(int i=1;i<n;i++)
dis[i]=dh[0][i]-dl[0][i]*mid;
for(int i=1;i<n;i++)
{
double mi=INF;//注意是double!!!
for(int j=1;j<n;j++)
if(!vis[j]&&mi>dis[j])
{
k=j;
mi=dis[j];
}
vis[k]=true;
ans+=mi;
for(int j=1;j<n;j++)
if(!vis[j]&&dis[j]>dh[k][j]-dl[k][j]*mid)
dis[j]=dh[k][j]-dl[k][j]*mid;
}
if(ans<0)//mid偏大
return true;
else
return false;
}
int main()
{
while(~scanf("%d",&n))
{
if(n==0)
break;
for(int i=0;i<n;i++)
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
memset(dl,0.0,sizeof(dl));
memset(dh,0.0,sizeof(dh));
for(int i=0;i<n;i++)
{
for(int j=0;j<i;j++)
{
dl[i][j]=dl[j][i]=sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
dh[i][j]=dh[j][i]=fabs(p[i].z-p[j].z);
}
}
double l=0.0,r=1000.0;
while(r-l>1e-5)
{
double mid=(l+r)/2;
if(prim(mid))
r=mid;
else
l=mid;
}
printf("%.3f\n",l);
}
}
这道题很迷的一直卡一直卡,最后我也没明白之前WA在哪儿了。。
还有一种迭代写法,我试了下,但是没弄成,这道题实在是不想看了,就先放这儿吧。。。
附上迭代写法的大佬博客:https://blog.csdn.net/zhang20072844/article/details/8176854
但是好像复制粘贴后没跑通???emmmmmm…