BZOJ1027 JSOI2007 合金 计算几何+最短路

题意:给定M个A物品和N个B物品,每个物品有x y z三个属性。求选择最少的B物品(每种物品的量是无限的,但不可拆分),使得可以组合出所有A物品,无解输出-1.
题解:题解在这里,有几个特殊情况需要判断……首先是所有金属在一条线上,其次是所有客户的金属在一条线段上。当然我是没判的,毕竟数据太弱了QAQ

#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 6666
#define eps 1e-8

const int MAXN=500+2;
struct Point{
    double x,y;

    Point operator-(Point a){
        Point Ans;
        Ans.x=x-a.x,Ans.y=y-a.y;
        return Ans;
    }
    double operator*(Point a){ return x*a.y-y*a.x;}
    double operator^(Point a){ return x*a.x+y*a.y;}
}a[MAXN],b[MAXN];
int N,M,d[MAXN][MAXN];
double z;

int Floyd(){
    int Ans=INF;

    for(int k=1;k<=M;k++)
        for(int i=1;i<=M;i++)
            if(d[i][k]<INF)
                for(int j=1;j<=M;j++)
                    d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    for(int i=1;i<=M;i++) Ans=min(Ans,d[i][i]);

    return Ans==INF?-1:Ans;
}

int main(){
    cin >> M >> N;
    for(int i=1;i<=M;i++) scanf("%lf %lf %lf",&a[i].x,&a[i].y,&z);
    for(int i=1;i<=N;i++) scanf("%lf %lf %lf",&b[i].x,&b[i].y,&z);

    memset(d,0X3F,sizeof(d));
    for(int i=1;i<=M;i++)
        for(int j=1;j<=M;j++)
            for(int k=1;k<=N;k++){
                z=(a[i]-b[k])*(a[j]-b[k]);
                if(z>eps) break;
                if(fabs(z)<eps && (a[i]-b[k]^a[j]-b[k])>eps) break;

                if(k==N) d[i][j]=1;
            }

    cout << Floyd() << endl;

    return 0;
}
View Code

 

posted @ 2017-02-26 00:54  WDZRMPCBIT  阅读(136)  评论(0编辑  收藏  举报