Thinking:
This problem is the combination of computing geometry and dijkstra algorithm. We consider bank1 and bank2 as two point. Consider each island as a point.
There are some things that attentions should be paid to:
(1) Do remember the last segment of a n>=4 polygon, which is vertix[1] and vertix[m].
(2) Do remember to try two end point of a segment when computing the minimum distance between the segment and polygon.
AC code:
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
double D[15];
bool visited[15];
double MIN(double a, double b)
{
if (a > b)
return b;
else return a;
}
struct edge{
int v, nxt;
double w;
};
edge E[500];
int total_edge;
int head[15];
void add_edge(int u, int v, double w)
{
E[total_edge].v = v;
E[total_edge].w = w;
E[total_edge].nxt = head[u];
head[u] = total_edge++;
}
struct point{
int x, y;
};
struct island{
int m;
point P[25];
};
island DAO[12];
point bank1[105];
point bank2[105];
double dis_p_to_p(point p1, point p2)
{
int dx = p1.x - p2.x;
int dy = p1.y - p2.y;
int temp = dx*dx + dy*dy;
return sqrt(temp);
}
double dot(point vec1, point vec2)
{
return vec1.x*vec2.x + vec1.y*vec2.y;
}
double cross(point v1, point v2)
{
return v1.x*v2.y - v2.x*v1.y;
}
double dis_point_to_line(point p1, point p2, point p3)
{
point vec;
vec.x = p1.x - p2.x;
vec.y = p1.y - p2.y;
point vec1;
vec1.x= p3.x - p1.x;
vec1.y = p3.y - p1.y;
point vec2;
vec2.x = p3.x - p2.x;
vec2.y = p3.y - p2.y;
if (dot(vec, vec1)*dot(vec, vec2)>= 0)
return MIN(dis_p_to_p(p1, p3), dis_p_to_p(p2, p3));
return fabs(cross(vec, vec1)) / dis_p_to_p(p1, p2);
}
double dis_line_to_polygon(point p1, point p2, int poly)
{
island I = DAO[poly];
double dis = 200000000;
for (int i = 1; i <= I.m; i++)
{
dis = MIN(dis, dis_point_to_line(p1, p2, I.P[i]));
}
for (int j = 1; j < I.m; j++)
{
dis = MIN(dis, dis_point_to_line(I.P[j], I.P[j + 1], p1));
dis = MIN(dis, dis_point_to_line(I.P[j], I.P[j + 1], p2));
}
dis = MIN(dis, dis_point_to_line(I.P[1], I.P[I.m], p1));
dis = MIN(dis, dis_point_to_line(I.P[1], I.P[I.m], p2));
return dis;
}
double polygon_to_polygon(int poly1,int poly2)
{
double dis = 200000000;
island L1 = DAO[poly1];
island L2 = DAO[poly2];
for (int i = 1; i <= L1.m; i++)
{
for (int j = 1; j < L2.m; j++)
dis = MIN(dis, dis_point_to_line(L2.P[j], L2.P[j + 1], L1.P[i]));
dis = MIN(dis, dis_point_to_line(L2.P[1], L2.P[L2.m], L1.P[i]));
}
for (int i = 1; i <= L2.m; i++)
{
for (int j = 1; j < L1.m; j++)
dis = MIN(dis, dis_point_to_line(L1.P[j], L1.P[j + 1], L2.P[i]));
dis = MIN(dis, dis_point_to_line(L1.P[1], L1.P[L1.m], L2.P[i]));
}
return dis;
}
int main()
{
//freopen("in.txt", "r", stdin);
int T;
cin >> T;
int r1, r2, n;
while (T--)
{
memset(head, -1, sizeof(head));
total_edge = 0;
scanf("%d%d%d", &r1, &r2, &n);
int bk2 = n + 1;
for (int i = 1; i < 15; i++)
D[i] = 200000000;
for (int i = 1; i <= r1; i++)
scanf("%d%d", &bank1[i].x, &bank1[i].y);
for (int i = 1; i <= r2; i++)
scanf("%d%d", &bank2[i].x, &bank2[i].y);
for (int i = 1; i <= n; i++)
{
scanf("%d", &DAO[i].m);
for (int j = 1; j <= DAO[i].m; j++)
scanf("%d%d", &DAO[i].P[j].x, &DAO[i].P[j].y);
}
double dis_b_b = 200000000;
for (int i = 1; i <= r1; i++) // bank to bank
for (int j = 1; j < r2; j++)
{
dis_b_b = MIN(dis_b_b, dis_point_to_line(bank2[j], bank2[j + 1], bank1[i]));
}
for (int i = 1; i <= r2; i++)
for (int j = 1; j < r1; j++)
{
dis_b_b = MIN(dis_b_b, dis_point_to_line(bank1[j], bank1[j + 1], bank2[i]));
}
add_edge(0, bk2, dis_b_b);
//add_edge(bk2, 0, dis_b_b);
//compute polygon
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
{
double temp = polygon_to_polygon(i, j);
add_edge(i, j, temp);
add_edge(j, i, temp);
}
// compute poly to bank1
for (int i = 1; i <= n; i++)
{
double temp = 200000000;
for (int j = 1; j < r1; j++)
{
temp = MIN(dis_line_to_polygon(bank1[j], bank1[j + 1], i), temp);
}
add_edge(0, i, temp);
}
for (int i = 1; i <= n; i++)
{
double temp = 200000000;
for (int j = 1; j < r2; j++)
{
temp = MIN(dis_line_to_polygon(bank2[j], bank2[j + 1], i), temp);
}
add_edge(i, bk2, temp);
}
D[0] = 0;
memset(visited, false, sizeof(visited));
for (int k = 1; k <= n + 2; k++)
{
int min = -1;
for (int i = 0; i <= bk2; i++)
{
if ((min == -1) && !visited[i])
min = i;
if ((D[i] < D[min])&&!visited[i])
min = i;
}
if (min == -1)
break;
visited[min] = true;
for (int a = head[min]; a != -1; a = E[a].nxt)
{
int v = E[a].v;
if (D[v] > D[min] + E[a].w)
D[v] = D[min] + E[a].w;
}
}
printf("%.3lf\n", D[bk2]);
}
return 0;
}