zoukankan      html  css  js  c++  java
  • BZOJ 1027 合金

    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

    3 2
    0.25 0.25 0.5
    0 0.6 0.5
    1 0 0
    0.7 0.1 0.2
    0.85 0.05 0.1

    Sample Output

    2

    HINT

     

    Source

    首先可以知道第三个比例是吃翔的(明显啊,1-前面两个就是第三个)。其次,我们再说一个结论:将合金的第一个比例看做x,第二个看做y,则n种合金所能形成的所有合金就是在这n种合金的凸包中(凸包的经典应用)。

    因此,问题转换为对目标点求凸包,在从给定点中找出一个闭包将目标凸包包裹起来。问题再一次转换,对于所有合法的边,我们要求的就是一个边权最小的环,就是求floyed求最小环。

    好,那么问题就来了。怎么连边呢,首先边不能穿过凸包,还有所有边的方向要跟凸包边的方向一致。(呵呵,慢慢写吧,我是不会告诉你有数据有鬼畜点的,WA了自己拍吧)。然后还有一点,有些特判不能省,详情见我code的spj。

      1 #include<ctime>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<cstdio>
      7 #include<cstdlib>
      8 using namespace std;
      9 
     10 #define rhl 100
     11 #define inf (1<<29)
     12 #define esp (1e-10)
     13 #define maxn 510
     14 int ans = inf,m,n,tot,dis[maxn][maxn];
     15 bool in[maxn];
     16 
     17 inline double equal(double a,double b) { return fabs(a-b) < esp; }
     18 
     19 inline bool dd(double a,double b) { if (equal(a,b)) return true; return a >= b; }
     20 inline bool dy(double a,double b) { if (equal(a,b)) return false; return a > b; }
     21 
     22 inline bool xd(double a,double b) { if (equal(a,b)) return true; return a <= b; }
     23 
     24 struct NODE
     25 {
     26     double x,y;
     27     friend inline bool operator == (NODE a,NODE b) { return equal(a.x,b.x)&&equal(a.y,b.y); }
     28     friend inline bool operator < (NODE a,NODE b) { if (a.x == b.x) return a.y < b.y; return a.x < b.x; }
     29     friend inline NODE operator - (NODE a,NODE b) { return (NODE) {a.x - b.x,a.y - b.y}; }
     30     friend inline double operator / (NODE a,NODE b) { return a.x*b.y-a.y*b.x; }
     31     inline NODE ra()
     32     {
     33         int xx,yy;
     34         do xx = rand()%rhl,yy = rand()%rhl;
     35         while (equal(1.0*xx,x)||equal(1.0*yy,y));
     36         return (NODE) {1.0*xx,1.0*yy};
     37     }
     38     inline void read() { scanf("%lf %lf",&x,&y); }
     39 }pri[maxn],aim[maxn],ch[maxn];
     40 struct LINE
     41 {
     42     double a,b,c;
     43     inline bool on(NODE p) { return equal(0,a*p.x+b*p.y+c); }
     44 };
     45 struct SEG
     46 {
     47     NODE a,b;
     48     inline LINE extend() { return (LINE) {a.y-b.y,b.x-a.x,b.y*(a.x-b.x)-b.x*(a.y-b.y)}; }
     49     inline bool on(NODE p)
     50     {
     51         if (p == a) return true;
     52         if (p == b) return true;
     53         return (dd(p.x,min(a.x,b.x))&xd(p.x,max(a.x,b.x)))&&(dd(p.y,min(a.y,b.y))&xd(p.y,max(a.y,b.y)));
     54     }
     55 };
     56 
     57 inline bool para(LINE l1,LINE l2) { return equal(l1.a * l2.b,l1.b * l2.a); }
     58 
     59 inline NODE cp(LINE l1,LINE l2)
     60 {
     61     double a1 = l1.a,b1 = l1.b,c1 = l1.c;
     62     double a2 = l2.a,b2 = l2.b,c2 = l2.c;
     63     double ry = (c2*a1-c1*a2)/(b1*a2-b2*a1),rx = (c1*b2-c2*b1)/(b1*a2-b2*a1);
     64     return (NODE) {rx,ry};
     65 }
     66 
     67 inline void convex()
     68 {
     69     sort(aim+1,aim+n+1);
     70     n = unique(aim+1,aim+n+1) - aim - 1;
     71     for (int i = 1;i <= n;++i)
     72     {
     73         while (tot > 1 &&(ch[tot] - ch[tot - 1])/(aim[i] - ch[tot-1]) <= 0) --tot;
     74         ch[++tot] = aim[i];
     75     }
     76     int k = tot;
     77     for (int i = n-1;i;--i)
     78     {
     79         while (tot > k &&(ch[tot] - ch[tot - 1])/(aim[i] - ch[tot-1]) <= 0) --tot;
     80         ch[++tot] = aim[i];
     81     }
     82     if (n > 1) --tot;
     83     ch[0] = ch[tot];
     84 }
     85 
     86 inline int find(NODE p)
     87 {
     88     NODE q = p.ra(); SEG s = (SEG) {p,q},t; LINE l = s.extend(),l1; int cnt;
     89     cnt = 0;
     90     for (int i = 1;i <= tot;++i)
     91     {
     92         t = (SEG) {ch[i],ch[i-1]};
     93         if ((t.extend()).on(p)&&t.on(p)) return false;
     94         l1 = t.extend();
     95         if (para(l,l1)) continue;
     96         q = cp(l,l1);
     97         if (dd(q.x,p.x)&&t.on(q)) ++cnt;
     98     }
     99     if (cnt & 1) return true;
    100     return false;
    101 }
    102 
    103 inline bool cross(NODE p,NODE q)
    104 {
    105     for (int i = 1;i <= tot;++i) 
    106         if (dy((q - p) / (ch[i] - p),0)) return false;   
    107     return true;
    108 }
    109 
    110 inline void ready()
    111 {
    112     sort(pri+1,pri+m+1);
    113     m = unique(pri+1,pri+m+1) - pri - 1;
    114     for (int i = 1;i <= m;++i) in[i] = find(pri[i]);
    115     memset(dis,0x7,sizeof(dis));
    116     for (int i = 1;i <= m;++i) if (!in[i])
    117         for (int j = 1;j <= m;++j)
    118             if (i != j && !in[j] &&dis[j][i] > maxn)
    119                 if (cross(pri[i],pri[j]))
    120                     dis[i][j] = 1;
    121 }
    122 
    123 inline void floyd()
    124 {
    125     for (int k = 1;k <= m;++k)
    126         for (int i = 1;i <= m;++i)
    127             if (dis[i][k] < maxn)
    128                 for (int j = 1;j <= m;++j)
    129                     dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
    130     for (int i = 1;i <= m;++i) ans = min(dis[i][i],ans);
    131     if (ans > maxn) ans = -1;
    132     for (int i = 1;i <= m;++i)
    133         for (int j = i+1;j <= m;++j)
    134         {
    135             SEG s = (SEG) {pri[i],pri[j]}; int k;
    136             for (k = 1;k <= n;++k)
    137                 if (!(equal((aim[k]-pri[i])/(aim[k]-pri[j]),0)&&s.on(aim[k]))) break;
    138             if (k == n + 1) { ans = 2; break; }
    139         }
    140     printf("%d",ans);
    141 }
    142 
    143 inline void spj() { if (n == 1) for (int i = 1;i <= m;++i) if (pri[i] == aim[1]) puts("1"),exit(0);  }
    144 
    145 int main()
    146 {
    147     freopen("1027.in","r",stdin);
    148     freopen("1027.out","w",stdout);
    149     srand(233);
    150     scanf("%d %d",&m,&n); double w;
    151     for (int i = 1;i <= m;++i)
    152         pri[i].read(),scanf("%lf",&w);
    153     for (int i = 1;i <= n;++i)
    154         aim[i].read(),scanf("%lf",&w);
    155     convex();
    156     spj();
    157     ready();
    158     floyd();
    159     fclose(stdin); fclose(stdout);
    160     return 0;
    161 }
    View Code
  • 相关阅读:
    【6666】分组背包
    Designing a RESTful API with Python and Flask 201
    把手账打印成书 把回忆装订成册
    sql基本操作语句
    sql serve基础
    sql serve存储过程
    TCP/IP 之 大明王朝邮差 (转)
    HBASE基础(4):语法(2) API (1) DDL
    bochsrc
    CentOS 6 bochs-2.6 gdb 调试 linux 0.11——bochsrc-hdc-gdb.bxrc
  • 原文地址:https://www.cnblogs.com/mmlz/p/4270884.html
Copyright © 2011-2022 走看看