zoukankan      html  css  js  c++  java
  • bzoj1027: [JSOI2007]合金

    http://www.lydsy.com/JudgeOnline/problem.php?id=1027

    因为x+y+z=1,所以z=1-x-y

    第三维可以忽略

    将x,y 看做 平面上的点

    简化问题:

    若只有两种 材料,那么可以合成 两点线段 上的所有的点

    推广到多种材料:

    若 用户点 在 材料点 构成的 凸包内,则可以合成

    所以题目转化为 求材料点 组成的 能包含所有用户点 的 最小环

    用Floyd

    枚举 每两对材料点,若所有用户点在 在线段的左侧或在线段上

    则 f[i][j]=1 表示i到j之间有一条边

    叉积判断 点在直线的哪一侧

    所以 如果是在 直线上,还要特判是否在线段上

    #include<cmath>
    #include<cstdio>
    #include<cstring> 
    #include<algorithm>
    
    using namespace std;
    
    #define N 501
    
    const double eps=1e-9;
    
    struct node
    {
        double x,y,z;
    }metal[N],user[N];
    
    int f[N][N];
    
    double cross(node a,node b,node p)
    {
        double xa=b.x-a.x;
        double ya=b.y-a.y;
        double xb=p.x-a.x;
        double yb=p.y-a.y;
        return xa*yb-xb*ya;
    }
    
    double getdis(node a,node b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    
    int main()
    {
        int m,n;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m;++i) scanf("%lf%lf%lf",&metal[i].x,&metal[i].y,&metal[i].z);
        for(int i=1;i<=n;++i) scanf("%lf%lf%lf",&user[i].x,&user[i].y,&user[i].z);
        memset(f,63,sizeof(f));
        int k;
        double tmp,dis1,dis2;
        for(int i=1;i<=m;++i)
        {
            for(int j=1;j<=m;++j)
            {
                for(k=1;k<=n;++k)
                {
                    tmp=cross(metal[i],metal[j],user[k]);
                    if(fabs(tmp)>eps)
                    {
                        if(tmp>0) continue;
                        break;
                    } 
                    dis1=getdis(metal[i],user[k]);
                    dis2=getdis(metal[i],metal[j]);
                    if(fabs(tmp)<eps && fabs(dis1-dis2)>eps && dis1>dis2) break;
                }
                if(k==n+1) f[i][j]=1;
            }
        }
        for(int k=1;k<=m;++k)
            for(int i=1;i<=m;++i)
                for(int j=1;j<=m;++j)
                    f[i][j]=min(f[i][k]+f[k][j],f[i][j]);
        int ans=m+1;
        for(int i=1;i<=m;++i) ans=min(ans,f[i][i]);
        if(ans==m+1) ans=-1;
        printf("%d",ans);
    }

    1027: [JSOI2007]合金

    Time Limit: 4 Sec  Memory Limit: 162 MB
    Submit: 4407  Solved: 1327
    [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
  • 相关阅读:
    ACM 一种排序
    ACM Binary String Matching
    ACM 括号配对问题
    ACM BUYING FEED
    ACM 喷水装置(二)
    ACM 会场安排问题
    ACM 推桌子
    ACM 心急的C小加
    ACM 田忌赛马
    ACM 疯牛
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7912091.html
Copyright © 2011-2022 走看看