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 }

 

 

你可能感兴趣的:(2007)