• BZOJ1027 [JSOI2007]合金 【计算几何 + floyd】


    题目

      某公司加工一种由铁、铝、锡组成的合金。他们的工作很简单。首先进口一些铁铝锡合金原材料,不同种类的
    原材料中铁铝锡的比重不同。然后,将每种原材料取出一定量,经过融解、混合,得到新的合金。新的合金的铁铝
    锡比重为用户所需要的比重。 现在,用户给出了n种他们需要的合金,以及每种合金中铁铝锡的比重。公司希望能
    够订购最少种类的原材料,并且使用这些原材料可以加工出用户需要的所有种类的合金。

    输入格式

      第一行两个整数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),分别表示铁铝锡在一种用户需要的合金中
    所占的比重。

    输出格式

     一个整数,表示最少需要的原材料种数。若无解,则输出–1。

    输入样例

    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

    输出样例

    5

    题解

    神题,蒟蒻跪了QAQ
    首先第三个点是赘余的,只要两个点满足条件,第三个点一定满足条件,因为它们的和为都为同一个定值

    这样我们就可以把材料和产品看做平面中的点,一个产品能被一些材料制作出来,当且仅当该产品在这些材料的凸包中。

    问题就变成了使用A集合中的点形成的最小凸包围住B集合中的所有点

    如果对A中的点i和j有所有B中的点都在其左侧,则连边i->j
    求一个最小环即可。
    此时B中的点一定在环上所有边左侧,即在该凸包内

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define Redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)
    #define eps 1e-9
    using namespace std;
    const int maxn = 505,maxm = 100005,INF = 1000000000;
    struct Point{double x,y;}A[maxn],B[maxn];
    int N,M,G[maxn][maxn],ans = INF;
    double cross(const Point& a,const Point& b){return a.x * b.y - a.y * b.x;}
    double dot(const Point& a,const Point& b){return a.x * b.x + a.y * b.y;}
    Point line(const Point& a,const Point& b){return (Point){b.x - a.x,b.y - a.y};}
    void floyd(){
        REP(k,N)
            REP(i,N)
                REP(j,N)
                    G[i][j] = min(G[i][j],G[i][k] + G[k][j]);
        REP(i,N) ans = min(ans,G[i][i]);
    }
    int main(){
        fill(G[0],G[0] + maxn * maxn,INF);
        scanf("%d%d",&N,&M); double t,tt;
        REP(i,N) scanf("%lf%lf%lf",&A[i].x,&A[i].y,&t);
        REP(i,M) scanf("%lf%lf%lf",&B[i].x,&B[i].y,&t);
        for (int i = 1; i <= N; i++)
            for (int j = 1,k; j <= N; j++){
                for (k = 1; k <= M; k++){
                    t = cross(line(A[i],B[k]),line(A[j],B[k]));
                    tt = dot(line(A[i],B[k]),line(A[j],B[k]));
                    if (t > eps) break;
                    if (fabs(t) < eps && tt > eps) break;
                }
                if (k == M + 1) G[i][j] = 1;
            }
        floyd();
        printf("%d
    ",ans == INF ? -1 : ans);
        return 0;
    }
    
  • 相关阅读:
    Python模糊查询本地文件夹去除文件后缀(7行代码)
    Python正则表达式
    python的logging模块
    Python中hashlib模块
    Python的os模块
    项目初始化mysql建库和授权
    Add correct host key in /root/.ssh/known_hosts to get rid of this message
    高中典型的等比数学题
    autoenv的使用方法
    celery任务进程关闭
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282715.html
Copyright © 2020-2023  润新知