Bzoj1027 [JSOI2007]合金
Posted SilverNebula
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj1027 [JSOI2007]合金相关的知识,希望对你有一定的参考价值。
Submit: 3823 Solved: 1115
Description
某公司加工一种由铁、铝、锡组成的合金。他们的工作很简单。首先进口一些铁铝锡合金原材料,不同种类的
原材料中铁铝锡的比重不同。然后,将每种原材料取出一定量,经过融解、混合,得到新的合金。新的合金的铁铝
锡比重为用户所需要的比重。 现在,用户给出了n种他们需要的合金,以及每种合金中铁铝锡的比重。公司希望能
够订购最少种类的原材料,并且使用这些原材料可以加工出用户需要的所有种类的合金。
Input
第一行两个整数m和n(m, n ≤ 500),分别表示原材料种数和用户需要的合金种数。第2到m + 1行,每行三
个实数a, b, c(a, b, c ≥ 0 且 a + b + c = 1),分别表示铁铝锡在一种原材料中所占的比重。第m + 2到m +
n + 1行,每行三个实数a, b, c(a, b, c ≥ 0 且 a + b + c = 1),分别表示铁铝锡在一种用户需要的合金中
所占的比重。
Output
一个整数,表示最少需要的原材料种数。若无解,则输出–1。
Sample Input
0.1 0.2 0.7
0.2 0.3 0.5
0.3 0.4 0.3
0.4 0.5 0.1
0.5 0.1 0.4
0.6 0.2 0.2
0.7 0.3 0
0.8 0.1 0.1
0.9 0.1 0
1 0 0
0.1 0.2 0.7
0.2 0.3 0.5
0.3 0.4 0.3
0.4 0.5 0.1
0.5 0.1 0.4
0.6 0.2 0.2
0.7 0.3 0
0.8 0.1 0.1
0.9 0.1 0
1 0 0
Sample Output
HINT
Source
由于a+b+c=1,第三维可以用前两维表示,所以可以不考虑。
二维情况下,几个点围成的区域就是它们可以表示出的区域。
枚举n中任意两点,若所有m点都在这两点所连有向线段的左边,则可以选。在邻接矩阵上标记出各点到另外点的转移关系,floyd求最小环即可。
然后特判所有点共点的情况。
——————
脑洞出一种奇怪的方法:
枚举凸包上某个点作为起点,遍历后面的凸包上点,如果m个点都在p[i] to p[i-2] 这条线段的左边,那么p[i],p[i-1],p[i-2]围成的三角形就没用了,可以把p[i-1]舍弃掉
枚举起点O(n),遍历凸包O(n),判是否可行O(m),总时间复杂度O(n*n*m)
拍了半天没问题的样子,但是交上去过不了,目测是在判断能否围成环的时候出了bug,要么就是少了什么特判
还是先放着吧
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const double eps=1e-8; 10 const int mxn=100010; 11 struct Point{ 12 double x,y; 13 Point operator + (Point b){ return (Point){x+b.x,y+b.y};} 14 Point operator - (Point b){ return (Point){x-b.x,y-b.y};} 15 double operator * (Point b){return x*b.x+y*b.y;} 16 bool operator < (Point b)const{ 17 return x<b.x || (x==b.x && y<b.y); 18 } 19 }p[mxn],a[mxn],bas[mxn]; 20 typedef Point Vector; 21 double Cross(Point a,Point b){return a.x*b.y-a.y*b.x;} 22 int n,m; 23 int ans; 24 bool judge(Point x,Point y){ 25 for(int i=1;i<=m;i++){ 26 double cro=Cross(y-x,a[i]-x); 27 if(cro<-eps)return 0; 28 if(fabs(cro)<eps && (x-a[i])*(y-a[i])>eps){ 29 return 0; 30 } 31 } 32 return 1; 33 } 34 35 int st[mxn],top,t2; 36 void Andrew(){ 37 sort(p+1,p+n+1); 38 for(int i=1;i<=n;i++){ 39 while(top>1 && Cross(p[st[top]]-p[st[top-1]],p[i]-p[st[top]])<0)top--; 40 st[++top]=i; 41 } 42 t2=top; 43 for(int i=n-1;i;i--){ 44 while(t2>top && Cross(p[st[t2]]-p[st[t2-1]],p[i]-p[st[t2]])<0)t2--; 45 st[++t2]=i; 46 } 47 for(int i=1;i<=t2;i++){ 48 printf("%.3f %.3f\n",p[st[i]].x,p[st[i]].y); 49 } 50 printf("fin\n");*/ 51 memcpy(bas,p,sizeof p); 52 for(int i=1;i<=t2;i++)p[i]=bas[st[i]]; 53 n=t2-1; 54 return; 55 } 56 void solve(int ST){ 57 // printf("st:%d\n",ST); 58 st[top=1]=ST; 59 for(int i=1,tmp=ST+1;i<n;i++,tmp++){ 60 if(tmp>n)tmp-=n; 61 if(top>1 && fabs(Cross(p[tmp]-p[st[top]],p[(tmp%n)+1]-p[tmp]))<eps)continue; 62 // printf("tmp:%d pt:%.3f %.3f\n",tmp,p[tmp].x,p[tmp].y); 63 bool flag=judge(p[st[top-1]],p[tmp]); 64 // printf("last:%.3f %.3f now:%.3f %.3f\n",p[st[top-1]].x,p[st[top-1]].y,p[tmp].x,p[tmp].y); 65 // printf("flag:%d\n",flag); 66 if(top>1 && flag){ 67 st[top]=tmp; 68 } 69 else if(judge(p[st[top]],p[tmp]))st[++top]=tmp; 70 else return; 71 } 72 if(top==2 && judge(p[st[top-1]],p[st[top]])){ 73 ans=min(ans,2);return; 74 } 75 if(st[top]==ST)top--; 76 if(!judge(p[st[top]],p[ST]))return; 77 ans=min(ans,top); 78 return; 79 } 80 bool SPJ(){ 81 for(int i=1;i<=n;i++) 82 if(fabs(p[i].x-p[1].x)>eps || fabs(p[i].y-p[1].y)>eps)return 0; 83 for(int i=1;i<=m;i++) 84 if(fabs(a[i].x-p[1].x)>eps || fabs(a[i].y-p[1].y)>eps)return 0; 85 return 1; 86 } 87 int main(){ 88 // freopen("Input.in","r",stdin); 89 int i,j; 90 scanf("%d%d",&n,&m); 91 for(i=1;i<=n;i++){ 92 scanf("%lf%lf%*lf",&p[i].x,&p[i].y); 93 } 94 for(i=1;i<=m;i++){ 95 scanf("%lf%lf%*lf",&a[i].x,&a[i].y); 96 } 97 if(!m){ 98 printf("0\n");return 0; 99 } 100 if(SPJ()){ 101 printf("1\n");return 0; 102 } 103 Andrew(); 104 ans=0x3f3f3f3f; 105 for(i=1;i<=n;i++){ 106 solve(i); 107 } 108 if(ans==0x3f3f3f3f || !ans)ans=-1; 109 printf("%d\n",ans); 110 return 0; 111 }
——————
正解floyd:
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const double eps=1e-8; 10 const int INF=0x3f3f3f3f; 11 const int mxn=10010; 12 struct Point{ 13 double x,y; 14 Point operator + (Point b){ return (Point){x+b.x,y+b.y};} 15 Point operator - (Point b){ return (Point){x-b.x,y-b.y};} 16 double operator * (Point b){return x*b.x+y*b.y;} 17 bool operator < (Point b)const{ 18 return x<b.x || (x==b.x && y<b.y); 19 } 20 }p[mxn],a[mxn],bas[mxn]; 21 typedef Point Vector; 22 double Cross(Point a,Point b){return a.x*b.y-a.y*b.x;} 23 int n,m; 24 int ans; 25 bool judge(Point x,Point y){ 26 for(int i=1;i<=m;i++){ 27 double cro=Cross(x-a[i],y-a[i]); 28 if(cro>eps)return 0; 29 if(fabs(cro)<eps && (x-a[i])*(y-a[i])>eps)return 0; 30 } 31 return 1; 32 } 33 bool SPJ(){ 34 for(int i=1;i<=n;i++) 35 if(fabs(p[i].x-p[1].x)>eps || fabs(p[i].y-p[1].y)>eps)return 0; 36 for(int i=1;i<=m;i++) 37 if(fabs(a[i].x-p[1].x)>eps || fabs(a[i].y-p[1].y)>eps)return 0; 38 return 1; 39 } 40 int mp[510][510]; 41 int main(){ 42 // freopen("Input.in","r",stdin); 43 int i,j; 44 scanf("%d%d",&n,&m); 45 for(i=1;i<=n;i++){ 46 scanf("%lf%lf%*lf",&p[i].x,&p[i].y); 47 // p[i].x*=10;p[i].y*=10; 48 } 49 if(!m){ printf("0\n");return 0;} 50 for(i=1;i<=m;i++){ 51 scanf("%lf%lf%*lf",&a[i].x,&a[i].y); 52 // a[i].x*=10;a[i].y*=10; 53 } 54 if(SPJ()){ 55 printf("1\n"); 56 return 0; 57 } 58 for(i=1;i<=n;i++){ 59 mp[i][i]=INF; 60 for(j=1;j<=n;j++){ 61 if(i==j)continue; 62 if(judge(p[i],p[j])) mp[i][j]=1; 63 else mp[i][j]=INF; 64 } 65 } 66 for(int k=1;k<=n;k++){ 67 for(i=1;i<=n;i++){ 68 for(j=1;j<=n;j++) 69 mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]); 70 } 71 } 72 ans=INF; 73 for(i=1;i<=n;i++)ans=min(ans,mp[i][i]); 74 if(ans==INF)ans=-1; 75 printf("%d\n",ans); 76 return 0; 77 }
以上是关于Bzoj1027 [JSOI2007]合金的主要内容,如果未能解决你的问题,请参考以下文章