zoukankan      html  css  js  c++  java
  • BZOJ_1027_[JSOI2007]_合金_(计算几何+Floyd求最小环)

    描述


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

    共三种金属,(m)种材料,给出每种材料中三种金属的占比.

    给出(n)种合金的三种金属占比.用材料做合金,问最少需要多少种材料.

    分析


    首先,由于三种金属的占比相加为1,所以确定了前两项,最后一项也就确定了,我们可以用二唯坐标((x,y))表示前两项,这样每种材料和合金就是二维平面上的一个点.

    接下来是用材料做合金.

    首先来考虑用两种材料做合金,两种材料为((x1,y1)和(x2,y2)).那么做成的合金就是((kx1+(1-k)x2,ky1+(1-k)y2) ,0leq{k}leq1).

    记两种材料为两个向量(overrightarrow{a},overrightarrow{b}),那么合金就是$$koverrightarrow{a}+(1-k)overrightarrow{b}$$

    等于$$koverrightarrow{a}+(1-k)overrightarrow{a}+(1-k)(overrightarrow{b}-overrightarrow{a})$$

    也就是说合金的点在两个材料的点所连的线段上.

    那么对于多个材料,我们把几个材料的点首尾相连,形成一个凸多边形,多边形内部的任意一点可以认为是在(多边形的两条边上的点所连的线段上),我们把那两个点做出来当作材料,就可以做出来多边形内部的点了.而多边形外部的点不在可做成的两点所连的线段上.

    如果连成的是凹多边形呢?可以去掉一些材料变成材料种类更少的凸多边形.

    所以就要把所有合金放在材料围成的多边形内部(或边上).我们把所有点都在同一侧的线段连一条长度为1的边,然后问题就转化为了求最小环,用Floyd即可.

    注意:特殊情况,即所有合金都与一个材料重合,此时答案是1.其他情况全部可以一般化.

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=500+5;
     5 const double eps=1e-10,INF=1<<27;
     6 int n,m;
     7 int d[maxn][maxn];
     8 inline int dcmp(double x){
     9     if(fabs(x)<eps) return 0;
    10     return x>0?1:-1;
    11 }
    12 struct pt{
    13     double x,y;
    14     pt(double x=0,double y=0):x(x),y(y){}
    15     pt operator - (const pt &a) const { return pt(x-a.x,y-a.y); }
    16     double operator * (const pt &a) const { return x*a.y-y*a.x; }
    17     double operator ^ (const pt &a) const { return x*a.x+y*a.y; }
    18     bool operator != (const pt &a) const { return (dcmp(a.x-x)||dcmp(a.y-y)); }
    19 }a[maxn],b[maxn];
    20 inline bool spj(){
    21     for(int i=1;i<=m;i++){
    22         bool flag=true;
    23         for(int j=1;j<=n;j++)if(a[i]!=b[j]){
    24             flag=false;
    25             break;
    26         }
    27         if(flag) return true;
    28     }
    29     return false;
    30 }
    31 inline bool J(pt p1,pt p2){
    32     for(int i=1;i<=n;i++)if(dcmp((b[i]-p1)^(b[i]-p2))>0) return false;
    33     return true;
    34 }
    35 inline int C(pt p1,pt p2){
    36     int l=0,r=0;
    37     for(int i=1;i<=n;i++){
    38         double t=(p2-p1)*(b[i]-p1);
    39         if(dcmp(t)>0) l++;
    40         else if(dcmp(t)<0) r++;
    41         if(l&&r) return 0;
    42     }
    43     if(!l&&!r&&J(p1,p2)) return 3;
    44     if(l) return 1;
    45     if(r) return 2;
    46     return 0;
    47 }
    48 inline void floyd(){
    49     for(int k=1;k<=m;k++)for(int i=1;i<=m;i++)for(int j=1;j<=m;j++)
    50         d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    51     int ans=INF;
    52     for(int i=1;i<=m;i++) ans=min(ans,d[i][i]);
    53     if(ans==INF){ puts("-1"); return; }
    54     printf("%d
    ",ans);
    55 }
    56 inline void solve(){
    57     if(spj()){ puts("1"); return; }
    58     for(int i=1;i<=m;i++)for(int j=i+1;j<=m;j++){
    59         int flag=C(a[i],a[j]);
    60         if(flag==1) d[i][j]=1;
    61         else if(flag==2) d[j][i]=1;
    62         else if(flag==3) d[i][j]=d[j][i]=1;
    63     }
    64     floyd();
    65 }
    66 inline void init(){
    67     scanf("%d%d",&m,&n); double t;
    68     for(int i=0;i<maxn;i++)for(int j=0;j<maxn;j++) d[i][j]=INF;
    69     for(int i=1;i<=m;i++) scanf("%lf%lf%lf",&a[i].x,&a[i].y,&t);
    70     for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&b[i].x,&b[i].y,&t);
    71 }
    72 int main(){
    73     init();
    74     solve();
    75     return 0;
    76 }
    View Code

    1027: [JSOI2007]合金

    Time Limit: 4 Sec  Memory Limit: 162 MB
    Submit: 3382  Solved: 955
    [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

  • 相关阅读:
    @Order
    uri和url , 以及末尾加不加 '/'
    windows删除右键新建多余选项
    Typora 指南
    常见状态码/HttpStatusCode
    final 修饰符
    4. shiro-整合redis
    springboot 整合mybatis 一级缓存失效
    springboot查看具体访问的url片段
    JavaSE:NIO
  • 原文地址:https://www.cnblogs.com/Sunnie69/p/5644462.html
Copyright © 2011-2022 走看看