zoukankan      html  css  js  c++  java
  • bzoj 1027 [JSOI2007]合金(计算几何+floyd最小环)

    1027: [JSOI2007]合金

    Time Limit: 4 Sec  Memory Limit: 162 MB
    Submit: 2970  Solved: 787
    [Submit][Status][Discuss]

    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

    【思路】

      几何+最小环  

      第三维可以由前两维确定所以不用考虑。

      两种原料可以合成的合金必在两点的线段上。推而广之,一堆点可以合成的合金一定在这堆点的凸包内。

      于是题目变成了,求一个点数最少的多边形使得所有需要的合金都在该多边形内部。

      对于两个点而言,如果所有点都在连线的一侧(这里视作左侧,边为有向边)或在边上则f[i][j]=1。

      做一遍floyd,min{f[i][i]}即为最小环的点数。

    【代码】

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     6 using namespace std;
     7 
     8 const int N = 500+10;
     9 const int INF = 1e9;
    10 const double eps = 1e-8;
    11 
    12 struct Pt {
    13     double x,y;
    14     Pt(double x=0,double y=0):x(x),y(y) {};
    15 };
    16 
    17 double cross(Pt a,Pt b,Pt c) { 
    18     return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); 
    19 }
    20 double Dot(Pt a,Pt b,Pt c) { return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y); }
    21 
    22 int n,m,f[N][N];
    23 Pt a[N],b[N];
    24 
    25 int solve() {
    26     FOR(i,1,m) FOR(j,1,m) {
    27         bool flag=1;
    28         FOR(k,1,n) {
    29             double c=cross(b[k],a[i],a[j]);
    30             if(c>eps || fabs(c)<eps && Dot(b[k],a[i],a[j])>eps) {
    31                 flag=0; break;
    32             }
    33         }
    34         if(flag) f[i][j]=1; else f[i][j]=INF;
    35     }
    36     int ans=INF;
    37     FOR(k,1,m) FOR(i,1,m) FOR(j,1,m)
    38         f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
    39     FOR(i,1,m) ans=min(ans,f[i][i]);
    40     if(ans==INF) return -1;
    41     else return ans;
    42 }
    43 
    44 int main() {
    45     scanf("%d%d",&m,&n);
    46     double x;
    47     FOR(i,1,m) scanf("%lf%lf%lf",&a[i].x,&a[i].y,&x);
    48     FOR(i,1,n) scanf("%lf%lf%lf",&b[i].x,&b[i].y,&x);
    49     printf("%d",solve());
    50     return 0;
    51 }
  • 相关阅读:
    BZOJ-1497 [NOI2006]最大获利 最小割
    BZOJ-2768 [JLOI2010]冠军调查 最小割
    BZOJ-3504 [Cqoi2014]危桥 最大流
    BZOJ-3894 文理分科 最小割
    HDU5196--DZY Loves Inversions 树状数组 逆序数
    【2013南京区域赛】部分题解 hdu4802—4812
    POJ1741--Tree (树的点分治) 求树上距离小于等于k的点对数
    SPOJ694 -- DISUBSTR 后缀树组求不相同的子串的个数
    POJ1743---Musical Theme (后缀数组+二分)
    POJ3729 Facer’s string 后缀数组
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5182994.html
Copyright © 2011-2022 走看看