bzoj 1027: [JSOI2007]合金
由于总和一定所以看前两个即可,可以他们抽象成平面上的点,两个点能合出来的点在以两点为端点的线段上,三个点的在以三点为顶点的三角形内,。。。
所以预先处理那两个点的连线在所有被需要的点的一边,便把距离设为1,跑一遍最小环就行了。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 #define M 509 9 #define EPS 1e-10 10 #define ll long long 11 using namespace std; 12 ll read() 13 { 14 char ch=getchar(); 15 ll x=0,f=1; 16 for(;ch<'0'||ch>'9';ch=getchar()) 17 if(ch=='-') 18 f=-1; 19 for(;ch>='0'&&ch<='9';ch=getchar()) 20 x=x*10+ch-'0'; 21 return x*f; 22 } 23 int n,m,f[M][M],mx=707406378; 24 struct data 25 { 26 double x,y; 27 }a[M],b[M]; 28 data operator -(data a1,data a2) 29 { 30 data a3; 31 a3.x=a1.x-a2.x; 32 a3.y=a1.y-a2.y; 33 return a3; 34 } 35 int jin(data a1,data a2) 36 { 37 double a3=a1.x*a2.y-a1.y*a2.x; 38 if(a3>EPS) 39 return 1; 40 if(a3<-EPS) 41 return -1; 42 return 0; 43 } 44 int cheng(data a1,data a2) 45 { 46 double a3=a1.x*a2.x+a1.y*a2.y; 47 if(a3>EPS) 48 return 1; 49 if(a3<-EPS) 50 return -1; 51 return 0; 52 } 53 bool pan1() 54 { 55 for(int i=1;i<=n;i++) 56 { 57 int sum=0; 58 for(int j=1;j<=m;j++) 59 if(a[i].x==b[j].x&&a[i].y==b[j].y) 60 sum++; 61 else 62 break; 63 if(sum==m) 64 return 1; 65 } 66 return 0; 67 } 68 bool pan2() 69 { 70 for(int i=3;i<=m;i++) 71 if(jin(a[i]-a[1],a[2]-a[1])!=0) 72 return 0; 73 for(int i=1;i<=n;i++) 74 for(int j=1;j<=n;j++) 75 { 76 int sum=0; 77 for(int k=1;k<=m;k++) 78 if(cheng(a[i]-b[k],a[j]-b[k])<=0) 79 sum++; 80 if(sum==m) 81 return 0; 82 } 83 return 1; 84 } 85 int main() 86 { 87 n=read(); 88 m=read(); 89 for(int i=1;i<=n;i++) 90 { 91 double a1; 92 scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a1); 93 } 94 for(int i=1;i<=m;i++) 95 { 96 double a1; 97 scanf("%lf%lf%lf",&b[i].x,&b[i].y,&a1); 98 } 99 if(pan1()) 100 { 101 printf("1\n"); 102 return 0; 103 } 104 if(pan2()) 105 { 106 printf("-1\n"); 107 return 0; 108 } 109 memset(f,127/3,sizeof(f)); 110 for(int i=1;i<=n;i++) 111 for(int j=1;j<=n;j++) 112 if(i!=j) 113 { 114 data a1=a[j]-a[i]; 115 int kg=1; 116 for(int k=1;k<=m;k++) 117 if(jin(a1,b[k]-a[i])<0) 118 { 119 kg=0; 120 break; 121 } 122 if(kg) 123 f[i][j]=kg; 124 } 125 for(int k=1;k<=n;k++) 126 for(int i=1;i<=n;i++) 127 for(int j=1;j<=n;j++) 128 f[i][j]=min(f[i][j],f[i][k]+f[k][j]); 129 for(int i=1;i<=n;i++) 130 mx=min(mx,f[i][i]); 131 if(mx==707406378) 132 mx=-1; 133 printf("%d\n",mx); 134 return 0; 135 } 136