• [JSOI2007]合金


    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
    第三维可以由前两维确定,所以可以忽略
    这样一个材料只有两个属性,把它变成一个坐标
    对于两个材料,他们能合成的合金就是以两个点为端点的线段上的点
    如果n个材料点构成的凸包囊括了所有合金点,就必然可行,因为一个合金点可以看作是某两个在凸包边上的点构成的线段上的点
    如果有合金点在a[i]->a[j]左边,没有合金点在右边
    那么建一条(i,j)权为1的边
    如果没有在左边的点,就建一条(j,i)边
    如果全在直线上,则不建边,特判
    于是转化为了floyd求最小环
    要特判所有点重点(可能输出1),和所有点在线段上(即输出2)
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 struct Node
      8 {
      9   double x,y;
     10 }a[501],b[501];
     11 double eps=1e-8;
     12 int dis[501][501],n,m,inf,ans;
     13 Node operator -(Node u,Node v)
     14 {
     15   return (Node){u.x-v.x,u.y-v.y};
     16 }
     17 double operator *(Node u,Node v)
     18 {
     19   return u.x*v.y-v.x*u.y;
     20 }
     21 bool spj()
     22 {int i,j;
     23   for (i=1;i<=n;i++)
     24     if (fabs(a[i].x-a[1].x)>eps||fabs(a[i].y-a[1].y)>eps) return 0;
     25   for (i=1;i<=m;i++)
     26     if (fabs(b[i].x-a[1].x)>eps||fabs(b[i].y-a[1].y)>eps) return 0;
     27   cout<<1<<endl;
     28   return 1;
     29 }
     30 bool pd(Node x,Node y)
     31 {int i,j;
     32   if (x.x>y.x) swap(x,y);
     33   for (i=1;i<=m;i++)
     34     {
     35       if (b[i].x<x.x||b[i].x>y.x) return 0;
     36     }
     37   if (x.y>y.y) swap(x,y);
     38   for (i=1;i<=m;i++)
     39     {
     40       if (b[i].y<x.y||b[i].y>y.y) return 0;
     41     }
     42   return 1;
     43 }
     44 int judge(Node x,Node y)
     45 {int i;
     46   int c1=0,c2=0;
     47   for (i=1;i<=m;i++)
     48     {
     49       double t=(y-x)*(b[i]-x);
     50       if (t>eps) c1++;
     51       if (t<-eps) c2++;
     52       if (c1*c2) return 0;
     53     }
     54   if (!c1&&!c2&&pd(x,y)) return -1;
     55   if (c1) return 1;
     56   if (c2) return 2;
     57   return 3;
     58 }
     59 int main()
     60 {int i,j,k;
     61   double d;
     62   cin>>n>>m;
     63   for (i=1;i<=n;i++)
     64     {
     65       scanf("%lf%lf%lf",&a[i].x,&a[i].y,&d);
     66     }
     67   for (i=1;i<=m;i++)
     68     {
     69       scanf("%lf%lf%lf",&b[i].x,&b[i].y,&d);
     70     }
     71   if (spj()) return 0;
     72   memset(dis,127/3,sizeof(dis));
     73   inf=dis[0][0];
     74   for (i=1;i<=n;i++)
     75     {
     76       for (j=i+1;j<=n;j++)
     77     {
     78       int p=judge(a[i],a[j]);
     79       if (p==-1)
     80         {
     81           cout<<2<<endl;
     82           return 0;
     83         }
     84       if (p==1) dis[i][j]=1;
     85       else if (p==2) dis[j][i]=1;
     86     }
     87     }
     88   for (k=1;k<=n;k++)
     89     {
     90       for (i=1;i<=n;i++)
     91     if (dis[i][k]!=inf)
     92     {
     93       for (j=1;j<=n;j++)
     94         if (dis[i][k]+dis[k][j]<dis[i][j])
     95         dis[i][j]=dis[i][k]+dis[k][j];
     96     }
     97     }
     98   ans=inf;
     99   for (i=1;i<=n;i++)
    100     ans=min(ans,dis[i][i]);
    101   if (ans==inf) cout<<"-1";
    102   else printf("%d
    ",ans);
    103 }
  • 相关阅读:
    【hive】时间段为五分钟的统计
    【git】提交到github不显示贡献小绿点问题的解决
    【hive】关于用户留存率的计算
    【hive】求日期是星期几
    【hive】数据仓库层次设计
    【hive】count() count(if) count(distinct if) sum(if)的区别
    转载:几种 hive join 类型简介
    丑小鸭和白天鹅没有区别
    好好照顾自己,就像照顾你爱的人那样;
    灵光一闪(最近更新于2020/8/23)
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8469721.html
Copyright © 2020-2023  润新知