首页 > 代码库 > bzoj1027: [JSOI2007]合金

bzoj1027: [JSOI2007]合金

http://www.lydsy.com/JudgeOnline/problem.php?id=1027

完全不会写然后听隔壁未来IOI爷讲的 Orzccz

因为第三维可以由前两维推出所以就变成了一些点

然后题目就可以转化为求一个最小的凸多边形使得所有点都在这个凸多边形内

然后就可以floyd

对于原材料合金中的两个,为坐标系中的两点,若所有需要的合金都在其一侧(不妨统一设为左侧),则连一条长度为1的有向边。

技术分享
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define rep(i,l,r) for(int i=l;i<=r;++i)
 7 using namespace std;
 8 const int N=520;
 9 typedef double d;
10 int n,m,ans,f[N][N],flag;
11 d c;
12 struct point{
13     d x,y;
14 }a[N],b[N];
15 typedef point vector;
16 const d eps=1e-7;
17 vector operator - (point a,point b){
18     return (vector){a.x-b.x,a.y-b.y};
19 }
20 d cross(vector a,vector b){
21     return a.x*b.y-a.y*b.x;
22 }
23 d cross(point a,point b,point c){  
24     return cross(b-a,c-a);
25 }
26 d dot(vector a,vector b){
27     return a.x*b.x+a.y*b.y;
28 }
29 d dot(point a,point b,point c){
30     return dot(b-a,c-a);
31 }
32 int main(){
33     scanf("%d%d",&n,&m);
34     rep(i,1,n)scanf("%lf%lf%lf",&a[i].x,&a[i].y,&c);
35     rep(i,1,m)scanf("%lf%lf%lf",&b[i].x,&b[i].y,&c);
36     memset(f,60,sizeof f);
37     rep(i,1,n) rep(j,1,n) {
38         flag=1;
39         rep(k,1,m){
40             c=cross(b[k],a[i],a[j]);
41             if(c>eps||(fabs(c)<eps&&dot(b[k],a[i],a[j])>eps)){
42                 flag=0;
43                 break; 
44             }
45         }
46         if(flag) f[i][j]=1;
47     }
48     rep(k,1,n) rep(i,1,n) rep(j,1,n) f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
49     ans=1e9;
50     rep(i,1,n) ans=min(ans,f[i][i]);
51     printf("%d\n",ans>=1e9?-1:ans);
52 }
View Code

 

bzoj1027: [JSOI2007]合金