bzoj1027 合金

凸包和FLOYD求最小环

思路:

1.第三维没用,舍弃,用前两维分别作为横纵坐标

2.求原材料的凸包,判断其是否包含所需要的合金,不是则无解

3.对凸包上的点建图
建图方法:枚举任意两点,若所有待加工合金均在两点所连直线的一侧,则设两点间距离为1,否则为最大值

凸包:学习矢量的减法、数量积、矢量积

double res=(a[i]-b[k])*(a[j]-b[k]);
if (res>EPS) break;//不在矢量区间
if (fabs(res)<EPS && ((a[i]-b[k])^(a[j]-b[k]))>EPS) break;//共线且不是线段上的点

代码:

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <queue>
#define EPS 1e-7
using namespace std;
const int N=505,INF=0x3f3f3f3f;
 struct ss
{
	double x,y;
	ss operator -(const ss z)
	{
		ss res;
		res.x=x-z.x; res.y=y-z.y;
		return res;
	}
	double operator *(const ss z)
	{
		return x*z.y-y*z.x;
	}
	double operator ^(const ss z)
	{
		return x*z.x+y*z.y;
	}
}a[N],b[N];
int m,n,Map[N][N],f[N][N],ans=INF;

 void floyd()
{
	memcpy(f,Map,sizeof(f));
	for (int k=1; k<=m; k++)
		for (int i=1; i<=m; i++)
			if (f[i][k]<INF)
				for (int j=1; j<=m; j++) f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
	for (int i=1; i<=m; i++) ans=min(ans,f[i][i]);
}

 int main()
{
	memset(Map,0x3f,sizeof(Map));
	scanf("%d%d",&m,&n);
	for (int i=1; i<=m; i++) scanf("%lf%lf%*lf",&a[i].x,&a[i].y);
	for (int i=1; i<=n; i++) scanf("%lf%lf%*lf",&b[i].x,&b[i].y);
	int i,j,k;
	for (i=1; i<=m; i++)
		for (j=1; j<=m; j++)
		{
			for (k=1; k<=n; k++)
			{
				double res=(a[i]-b[k])*(a[j]-b[k]);
				if (res>EPS) break;
				if (fabs(res)<EPS && ((a[i]-b[k])^(a[j]-b[k]))>EPS) break;
			}
			if (k==n+1) Map[i][j]=1;
		}
	floyd();
	if (ans==INF) ans=-1;
	printf("%d\n",ans);
	return 0;
}
posted @ 2020-06-20 21:22  Allen_Gun  阅读(123)  评论(0编辑  收藏  举报