真是很好的计算几何题啊!~
转化为二维问题,第三维可以由前两维确定,所以可以不用管。
然后两种原料能配成的产品一定在两个点的线段上。
转化成在m个点里找最少点,使其完全包含那n个点。
floyd最小环。。
PS:网上的貌似都是错了。。
2 1
0 0 1
0 0.5 0.5
0 1 0
答案:-1
细节啊!!!
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 #include <cmath> 7 8 #define N 1010 9 #define EPS 1e-10 10 #define INF 0x3f3f3f3f 11 12 using namespace std; 13 14 struct PO 15 { 16 double x,y; 17 }p[N],s[N]; 18 19 int n,m,dis[N][N]; 20 21 inline int dc(double x) 22 { 23 if(x>EPS) return 1; 24 else if(x<-EPS) return -1; 25 return 0; 26 } 27 28 inline double cross(const PO &a,const PO &b,const PO &c) 29 { 30 return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); 31 } 32 33 inline double dot(const PO &a,const PO &b,const PO &c) 34 { 35 return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y); 36 } 37 38 inline void read() 39 { 40 scanf("%d%d",&m,&n); 41 double tmp; 42 for(int i=1;i<=m;i++) 43 scanf("%lf%lf%lf",&p[i].x,&p[i].y,&tmp); 44 for(int i=1;i<=n;i++) 45 scanf("%lf%lf%lf",&s[i].x,&s[i].y,&tmp); 46 } 47 48 inline bool check(const PO &a,const PO &b) 49 { 50 for(int i=1;i<=n;i++) 51 if(dc(cross(a,b,s[i]))<0) return false; 52 return true; 53 } 54 55 inline void prep() 56 { 57 memset(dis,0x3f,sizeof dis); 58 for(int i=1;i<=m;i++) 59 for(int j=1;j<=m;j++) 60 { 61 if(i==j) continue; 62 if(check(p[i],p[j])) dis[i][j]=1; 63 } 64 } 65 66 inline bool onpoint() 67 { 68 for(int i=1;i<=m;i++) 69 { 70 int cnt=0; 71 for(int j=1;j<=n;j++) 72 { 73 if(dc(p[i].x-s[j].x)==0&&dc(p[i].y-s[j].y)==0) cnt++; 74 else break; 75 } 76 if(cnt==n) return true; 77 } 78 return false; 79 } 80 81 inline bool onseg()//如果所有点共线,且没有一条线段包含他们所有点 82 { 83 for(int i=3;i<=n;i++) 84 if(dc(cross(s[1],s[2],s[i]))!=0) return false; 85 for(int i=1;i<=m;i++) 86 for(int j=i+1;j<=m;j++) 87 { 88 int cnt=0; 89 for(int k=1;k<=n;k++) 90 if(dc(dot(s[k],p[i],p[j]))<=0) cnt++; 91 if(cnt==n) return false; 92 } 93 return true; 94 } 95 96 inline void go() 97 { 98 if(n==0) {puts("0");return;} 99 if(onpoint()) {puts("1");return;} 100 if(onseg()) {puts("-1");return;} 101 int ans=INF; 102 prep(); 103 for(int k=1;k<=m;k++) 104 for(int i=1;i<=m;i++) 105 if(dis[i][k]<INF) 106 for(int j=1;j<=m;j++) 107 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); 108 for(int i=1;i<=m;i++) ans=min(ans,dis[i][i]); 109 if(ans==INF) ans=-1; 110 printf("%d\n",ans); 111 } 112 113 int main() 114 { 115 read(),go(); 116 return 0; 117 }