UVA 10514 【computing geometry】

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值