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