BZOJ 1027 [JSOI2007]合金

真是很好的计算几何题啊!~

转化为二维问题,第三维可以由前两维确定,所以可以不用管。

然后两种原料能配成的产品一定在两个点的线段上。

转化成在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 }

 

 

posted @ 2013-03-05 21:29  proverbs  阅读(1095)  评论(0编辑  收藏  举报