BZOJ P1027[JSOI2007]合金

来源:互联网 发布:淘宝中国质造加入条件 编辑:程序博客网 时间:2024/05/17 02:00

大概算是第一道的计算几何题??

我们可以发现给出的三个量相加等于一,别跟我说样例,所以可以忽略一项

然后我们可以发现,如果要混合出一样东西,假设是x1,y1.x2,y2混合出x3,y3

(x1<x2,y1<y2)那么可以发现x1<x3<x2&&y1<y3<y2

所以题目就是要找一些点这些点连出来的多边形可以包含所有点

这样就是个凸包了,然后floyed跑个最短路

我的注释多详细

#include<iostream>#include<algorithm>#include<cmath>#include<cstring>#include<cstdio>#define eps 1e-10#define inf 100000000using namespace std;struct P{double x,y;};P a[505],b[505];int dis[505][505],mp[505][505],n,m;double operator*(P a,P b){return a.x*b.y-a.y*b.x;}//求点积 P operator-(P a,P b){P t;t.x=a.x-b.x;t.y=a.y-b.y;return t;}//点的差求出向量 bool col(P x,P y){if(x.x>y.x){swap(x,y);}for(int i=1;i<=m;i++){if(b[i].x<x.x||b[i].x>y.x){return 0;}}//判断是否都在x,y的线段上 if(x.y>y.y){swap(x,y);}for(int i=1;i<=m;i++){if(b[i].y<x.y||b[i].y>y.y){return 0;}}//判断是否都在x,y的线段上 return 1;}int jud(P x,P y){int c1=0,c2=0;for(int i=1;i<=m;i++){double t=(y-x)*(b[i]-x);//点积来计算两个向量的位置关系 if(t>eps){c1++;}//在顺时针位置 if(t<-eps){c2++;}//逆时针 if(c1*c2){return 0;}//两边都有的话,直接不连边 }if(!c1&&!c2&&col(x,y)){cout<<2<<endl;return -1;}//如果正好在这条线上,并且所有点都可以被包住,直接输出2 if(c1){return 1;}//如果只有顺时针 if(c2){return 2;}//只有逆时针 return 3;//第五种情况就是所有点在同一直线但是x,y并不包含所有点 }void floyd(){int ans=inf;for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){if(dis[i][k]<inf){for(int j=1;j<=n;j++){dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);}}}}//floyed求一下传递闭包,最短路 for(int i=1;i<=n;i++){ans=min(ans,dis[i][i]);}//算一算以一个点为顶点的传递闭包的最短路 if(ans==inf||ans<=2){cout<<"-1"<<endl;}else{printf("%d",ans);}}void solve(){for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){int flag=jud(a[i],a[j]);if(flag==-1){return;}//已经包住了,返回 if(flag==1){dis[i][j]=1;//都在左侧 }else if(flag==2){dis[j][i]=1;//都在右侧 }else if(flag==3){dis[i][j]=dis[j][i]=1;//都在线上 }}}floyd();//求传递闭包 }bool spj(){for(int i=1;i<=n;i++){if(fabs(a[i].x-a[1].x)>eps||fabs(a[i].y-a[1].y)>eps){return 0;}}for(int i=1;i<=m;i++){if(fabs(b[i].x-a[1].x)>eps||fabs(b[i].y-a[1].y)>eps){return 0;}}puts("1");return 1;}int main(){memset(dis,127/3,sizeof(dis));cin>>n>>m;double K;for(int i=1;i<=n;i++){cin>>a[i].x>>a[i].y>>K;}//这个K。。。。 for(int i=1;i<=m;i++){cin>>b[i].x>>b[i].y>>K;}//这个K。。。。 if(spj()){return 0;}solve();return 0;}/*in:3 20.25 0.25 0.50 0.6 0.41 0 00.7 0.1 0.20.85 0.05 0.1out:2*/ 


1 0
原创粉丝点击