• BZOJ 1027 [JSOI2007]合金


    真是很好的计算几何题啊!~

    转化为二维问题,第三维可以由前两维确定,所以可以不用管。

    然后两种原料能配成的产品一定在两个点的线段上。

    转化成在m个点里找最少点,使其完全包含那n个点。

    floyd最小环。。

    PS:网上的貌似都是错了。。

    2 1

    0 0 1

    0 0.5 0.5

    0 1 0

    答案:-1

    细节啊!!!

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <algorithm>
      6 #include <cmath>
      7 
      8 #define N 1010
      9 #define EPS 1e-10
     10 #define INF 0x3f3f3f3f
     11 
     12 using namespace std;
     13 
     14 struct PO
     15 {
     16     double x,y;
     17 }p[N],s[N];
     18 
     19 int n,m,dis[N][N];
     20 
     21 inline int dc(double x)
     22 {
     23     if(x>EPS) return 1;
     24     else if(x<-EPS) return -1;
     25     return 0;
     26 }
     27 
     28 inline double cross(const PO &a,const PO &b,const PO &c)
     29 {
     30     return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
     31 }
     32 
     33 inline double dot(const PO &a,const PO &b,const PO &c)
     34 {
     35     return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y);
     36 }
     37 
     38 inline void read()
     39 {
     40     scanf("%d%d",&m,&n);
     41     double tmp;
     42     for(int i=1;i<=m;i++)
     43         scanf("%lf%lf%lf",&p[i].x,&p[i].y,&tmp);
     44     for(int i=1;i<=n;i++)
     45         scanf("%lf%lf%lf",&s[i].x,&s[i].y,&tmp);
     46 }
     47 
     48 inline bool check(const PO &a,const PO &b)
     49 {
     50     for(int i=1;i<=n;i++)
     51         if(dc(cross(a,b,s[i]))<0) return false;
     52     return true;
     53 }
     54 
     55 inline void prep()
     56 {
     57     memset(dis,0x3f,sizeof dis);
     58     for(int i=1;i<=m;i++)
     59         for(int j=1;j<=m;j++)
     60         {
     61             if(i==j) continue;
     62             if(check(p[i],p[j])) dis[i][j]=1;
     63         }
     64 }
     65 
     66 inline bool onpoint()
     67 {
     68     for(int i=1;i<=m;i++)
     69     {
     70         int cnt=0;
     71         for(int j=1;j<=n;j++)
     72         {
     73             if(dc(p[i].x-s[j].x)==0&&dc(p[i].y-s[j].y)==0) cnt++;
     74             else break;
     75         }
     76         if(cnt==n) return true;
     77     }
     78     return false;
     79 }
     80 
     81 inline bool onseg()//如果所有点共线,且没有一条线段包含他们所有点
     82 {
     83     for(int i=3;i<=n;i++)
     84         if(dc(cross(s[1],s[2],s[i]))!=0) return false;
     85     for(int i=1;i<=m;i++)
     86         for(int j=i+1;j<=m;j++)
     87         {
     88             int cnt=0;
     89             for(int k=1;k<=n;k++)
     90                 if(dc(dot(s[k],p[i],p[j]))<=0) cnt++;
     91             if(cnt==n) return false;
     92         }
     93     return true;
     94 }
     95 
     96 inline void go()
     97 {
     98     if(n==0) {puts("0");return;}
     99     if(onpoint()) {puts("1");return;}
    100     if(onseg()) {puts("-1");return;}
    101     int ans=INF;
    102     prep();
    103     for(int k=1;k<=m;k++)
    104         for(int i=1;i<=m;i++)
    105             if(dis[i][k]<INF)
    106                 for(int j=1;j<=m;j++)
    107                     dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    108     for(int i=1;i<=m;i++) ans=min(ans,dis[i][i]);
    109     if(ans==INF) ans=-1;
    110     printf("%d\n",ans);
    111 }
    112 
    113 int main()
    114 {
    115     read(),go();
    116     return 0;
    117 }
  • 相关阅读:
    c++:资源管理(RAII)、new/delete的使用、接口设计与声明、swap函数
    C++普通链表增删、倒序打印
    Android-UI:按钮监听&文字/图片/进度条&动态变更&dialog&布局&自定义布局/控件/响应事件
    Android-活动生命周期&Bundle回收临时数据&活动启动模式&常用技巧
    C++字符串空格替换题
    C++二维数组查找题
    c++:const、初始化、copy构造/析构/赋值函数
    C++赋值运算符函数
    Android-活动创建&Toast&Menu&Intent
    用yarn代替cnpm,cnpm漏包有点严重
  • 原文地址:https://www.cnblogs.com/proverbs/p/2945104.html
Copyright © 2020-2023  润新知