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