Bzoj1027 [JSOI2007]合金

Posted SilverNebula

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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]合金的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj1027 [JSOI2007]合金

bzoj1027JSOI2007合金

[BZOJ]1027 合金(JSOI2007)

[bzoj1027][JSOI2007]合金

BZOJ1027 [JSOI2007]合金

bzoj1027: [JSOI2007]合金