首页 > 代码库 > Bzoj1027 [JSOI2007]合金

Bzoj1027 [JSOI2007]合金

Time Limit: 4 Sec  Memory Limit: 162 MB
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

10 10
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

5

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]合金