紀念一下此題,雖然不難,但是寫起來比較麻煩,很多人直接套了許多模板過的,標程是採用二分的方法,我是採用一般方式進行遞推,不斷尋找中垂線。順便把標程貼上
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
struct Line
{
double b,k;
int f;
};
double city[55][2];
double st[55][2];
int n,m;
bool v[55];
int solve(int A,int B)
{
if(A==B) return 0;
double x=city[A][0],y=city[A][1];
int pos=-1,Sum=0;
double a,b;
double s=10000000;
for(int i=0; i<m; ++i)
{
double c=sqrt((x-st[i][0])*(x-st[i][0])+(y-st[i][1])*(y-st[i][1]));
if(c<s) s=c,pos=i;
}
x=st[pos][0],y=st[pos][1];
memset(v,0,sizeof(v));
v[pos]=1;
Line li_ci;
if(fabs(city[B][0]-city[A][0])<0.0000001) li_ci.f=-1,li_ci.b=city[B][0];
else
{
li_ci.k=(city[A][1]-city[B][1])/(city[A][0]-city[B][0]);
li_ci.b=city[A][1]-li_ci.k*city[A][0];
li_ci.f=0;
}
double u=city[A][0];
if(li_ci.f==-1) u=city[A][1];
while(1)
{
int flag=0,p=-1;
double q;
for(int j=0; j<m; ++j)
if(!v[j])
{
Line st_st;
if(fabs(y-st[j][1])<0.0000001) st_st.f=-1,st_st.b=(x+st[j][0])/2;
else
{
st_st.f=0;
st_st.k=-(x-st[j][0])/(y-st[j][1]);
a=(y+st[j][1])/2;
b=(x+st[j][0])/2;
st_st.b=a-st_st.k*b;
}
if((li_ci.f==-1&&st_st.f==-1)||(!li_ci.f&&!st_st.f&&fabs(li_ci.k-st_st.k)<0.0000001)) continue;
if(li_ci.f!=-1)
{
if(st_st.f==-1) a=st_st.b;
else a=(st_st.b-li_ci.b)/(li_ci.k-st_st.k);
if(a>=max(u,city[B][0])||a<=min(u,city[B][0])) continue;
if(!flag) flag=1,p=j,q=a;
else if((u<city[B][0]&&a<q)||(u>city[B][0]&&a>q)) p=j,q=a;
continue;
}
else
{
if(fabs(st_st.k)<0.0000001) a=st_st.b;
else a=st_st.k*li_ci.b+st_st.b;
if(a>=max(u,city[B][1])||a<=min(u,city[B][1])) continue;
if(!flag) flag=1,p=j,q=a;
else if((u<city[B][1]&&a<q)||(u>city[B][1]&&a>q)) p=j,q=a;
continue;
}
}
if(p==-1) break;
++Sum;
v[pos=p]=1;
x=st[p][0],y=st[p][1];
u=q;
}
return Sum;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("ou.txt","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1; i<=n; ++i) scanf("%lf%lf",&city[i][0],&city[i][1]);
for(int i=0; i<m; ++i) scanf("%lf%lf",&st[i][0],&st[i][1]);
int x,y,s;
scanf("%d",&s);
for(int i=1; i<=s; ++i)
{
scanf("%d%d",&x,&y);
printf("%d\n",solve(x,y));
}
}
return 0;
}
標程:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
#define N 53
#define eps 1e-11
#define inf 1e10
struct POINT {
double x, y;
POINT() {};
POINT(double _x, double _y): x(_x), y(_y) {};
}c[N], b[N];
int n, m;
inline double dist(POINT &x, POINT &y) {
return ((x.x-y.x)*(x.x-y.x) + (x.y-y.y)*(x.y-y.y));
}
int belong(POINT &x) {
double r = inf, d;
int k = 0;
for (int i=0; i<m; i++) {
d = dist(x, b[i]);
if (d < r) { r = d; k = i; }
}
return k;
}
int work(POINT &x, POINT &y) {
int la = belong(x), lb = belong(y);
if (la == lb) return 0;
if (sqrt(dist(x, y)) < eps) return 1;
POINT t((x.x+y.x)/2.0, (x.y+y.y)/2.0);
return work(x, t) + work(t, y);
}
int main() {
int k, x, y;
while (scanf("%d%d", &n, &m) == 2) {
for (int i=0; i<n; i++) scanf("%lf%lf", &c[i].x, &c[i].y);
for (int i=0; i<m; i++) scanf("%lf%lf", &b[i].x, &b[i].y);
scanf("%d", &k);
while (k--) {
scanf("%d%d", &x, &y);
printf("%d\n", work(c[x-1], c[y-1]));
}
}
return 0;
}