• 【BZOJ】【1027】【JSOI2007】合金


    计算几何/凸包/Floyd


      Orz rausen大爷太强辣

      计算几何题目果然不会做>_>

      这个题……虽然他给了3个坐标,但实际上是个二维的计算几何题= =因为第三维坐标可以直接用前两维坐标表示出来。

      考虑一下这些二维平面上的点的意义……

      假如我们现在手里有一种原材料$(x_1,y_1)$,那么我们就只能搞出这一种合金= =

      那么如果有两种原材料,我们配一配,就可以配出$(x_1,y_1)$到$(x_2,y_2)$这条线段上的所有合金= =

      如果有三种,我们能配出的就是那个三角形区域的所有种类的合金……

      以此类推……我们有n种原材料,我们能搞出的合金就是这n个点的凸包围出来的区域。

      

      所以问题就变成了:从n个点中选出最少的p个点使得给定的m个点全部在这p个点的凸包内(主要意思是这样,当然还有一些边界情况,嗯就是共线、共点……)

      这个是用floyd求最小环来做的……对于每对点(i,j),如果m个点都在向量(i->j)的左边,则连边 i->j 权值为1,那么$ans=min{dist[i][i]}$

    P.S.好像没有用到求凸包的算法……不过用了凸包的思想……

     1 /**************************************************************
     2     Problem: 1027
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:1172 ms
     7     Memory:2288 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 1027
    11 #include<cmath>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 using namespace std;
    21 typedef long long LL;
    22 inline int getint(){
    23     int r=1,v=0; char ch=getchar();
    24     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
    25     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
    26     return r*v;
    27 }
    28 typedef double lf;
    29 const lf eps=1e-8;
    30 const int N=505,INF=1e9;
    31 /*******************template********************/
    32 int n,m,d[N][N];
    33 struct Point{
    34     double x,y;
    35     Point(){}
    36     Point(lf x,lf y):x(x),y(y){}
    37     void read(){scanf("%lf%lf%*lf",&x,&y);}
    38     inline bool operator != (const Point &p)const{
    39         return fabs(x-p.x) > eps || fabs(y-p.y) > eps;
    40     }
    41 }a[N],b[N];
    42 typedef Point Vector;
    43 Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
    44 lf Cross(Point a,Point b){return a.x*b.y-a.y*b.x;}
    45  
    46 bool in_one_line(Point x,Point y){
    47     if (x.x > y.x) swap(x,y);
    48     F(i,1,m) if (b[i].x < x.x || b[i].x > y.x) return 0;
    49     if (x.y > y.y) swap(x,y);
    50     F(i,1,m) if (b[i].y < x.y || b[i].y > y.y) return 0;
    51     return 1;
    52 }
    53 int check(Point x,Point y){
    54     int cnt1=0,cnt2=0; lf tmp;
    55     F(i,1,m){
    56         tmp=Cross(y-x,b[i]-x);
    57         if (tmp>eps) ++cnt1;
    58         if (tmp<-eps) ++cnt2;
    59         if (cnt1 && cnt2) return 0;
    60     }
    61     if (!cnt1 && !cnt2 && in_one_line(x,y)){
    62         puts("2");
    63         return -1;
    64     }
    65     return cnt1 ? 1 : cnt2 ? 2 : 3;
    66 }
    67 void Floyd(){
    68     int ans=INF;
    69     F(k,1,n) F(i,1,n) F(j,1,n)
    70         d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    71     F(i,1,n) ans=min(ans,d[i][i]);
    72     if (ans==INF || ans<=2) puts("-1");
    73     else printf("%d
    ",ans);
    74 }
    75 void solve(){
    76     F(i,1,n) F(j,1,n) d[i][j]=INF;
    77     F(i,1,n) F(j,i+1,n){
    78         int f=check(a[i],a[j]);
    79         if (f==-1) return;
    80         if (f==1) d[i][j]=1;
    81         else if (f==2) d[j][i]=1;
    82         else if (f==3) d[i][j]=d[j][i]=1;
    83     }
    84     Floyd();
    85 }
    86 bool spj(){
    87     F(i,1,n) if (a[1]!=a[i]) return 0;
    88     F(i,1,m) if (a[1]!=b[i]) return 0;
    89     puts("1");
    90     return 1;
    91 }
    92 int main(){
    93     n=getint(); m=getint();
    94     F(i,1,n) a[i].read();
    95     F(i,1,m) b[i].read();
    96     if (spj()) return 0;
    97     solve();
    98     return 0;
    99 }
    View Code

    1027: [JSOI2007]合金

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

    [Submit][Status][Discuss]
  • 相关阅读:
    [C++]Linux之进程间通信小结【待完善】
    [转] thrift的使用介绍
    [转] splice系列系统调用
    [转] gdb中忽略信号处理
    [转] 确定性投资的框架
    [转] 投资策略及投资体系
    [转] 为什么医疗咨询服务公司Evolent Health仅用4年就华丽上市?
    [转] When exactly does the virtual table pointer (in C++) gets set for an object?
    [转] Linux写时拷贝技术(copy-on-write)
    [转] .bss段和.data段的区别
  • 原文地址:https://www.cnblogs.com/Tunix/p/4424105.html
Copyright © 2020-2023  润新知