• bzoj1390 [CEOI2008] Fence


    题意

    给出n个白点和m个黑点.现在你需要选择一些白点把黑点圈起来.每有一个黑点不能被选出的白点组成的凸包包含就需要付出111的代价,每选出一个白点就需要付出20的代价.要求最小化代价之和
    n,m<=100

    分析

    首先选出三个白点的代价小于扔掉一个黑点的代价,那么显然我们要尽量多地圈黑点.对所有白点求一个凸包,此时包含的黑点数目达到最多,但不一定是最优方案,因为也许可以少选一些白点,包含同样数目的黑点.那么就是选出尽量少的白点使得它们包含之前被凸包包含的黑点.这里我脑抽了一下...实际上推到这里和JSOI 合金 已经等价了,建图跑最小环即可.
    因为是计算几何题,所以往CEOI官网扒了数据测了一发过了才敢往bzoj交

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=105;
    struct point{
      double x,y;
      point(){}
      point(double a,double b){x=a;y=b;}
      void read(){
        scanf("%lf%lf",&x,&y);
      }
      bool operator <(const point &B)const{
        return (x==B.x)?y<B.y:x<B.x;
      }
      bool operator ==(const point &B)const{
        return x==B.x&&y==B.y;
      }
    }P1[maxn],P2[maxn],P3[maxn],stk[maxn];int top=0,cnt=0;
    point operator +(const point &A,const point &B){
      return point(A.x+B.x,A.y+B.y);
    }
    point operator -(const point &A,const point &B){
      return point(A.x-B.x,A.y-B.y);
    }
    double cross(const point &A,const point &B){
      return A.x*B.y-A.y*B.x;
    }
    void convexhull(point *P,int n){
      sort(P+1,P+n+1);
      stk[top++]=P[1];
      for(int i=2;i<=n;++i){
        while(top>1&&cross(stk[top-1]-stk[top-2],P[i]-stk[top-2])>=0)top--;
        stk[top++]=P[i];
      }
      int lim=top;
      for(int i=n-1;i>=1;--i){
        while(top>lim&&cross(stk[top-1]-stk[top-2],P[i]-stk[top-2])>=0)top--;
        stk[top++]=P[i];
      }
      --top;
    }
    bool betw(double x,double a,double b){
      return (a<=x&&x<=b)||(b<=x&&x<=a);
    }
    bool onseg(point o,point A,point B){
      return betw(o.x,A.x,B.x)&&cross(A-o,B-o)==0;
    }
    bool inside(point x,point A,point B,point C){
      if(x==A||x==B||x==C)return true;
      if(onseg(x,A,B)||onseg(x,A,C)||onseg(x,B,C))return true;
      int s1=(cross(B-A,x-A)>0),s2=(cross(C-B,x-B)>0),s3=(cross(A-C,x-C)>0);
      return s1==s2&&s2==s3;
    }
    bool inside(point A){
      if(cross(stk[1]-stk[0],A-stk[0])>0)return false;
      if(cross(stk[top-1]-stk[0],A-stk[0])<0)return false;
      int l=1,r=top-1;
      while(l<=r){
        int mid=(l+r)>>1;
        if(cross(stk[mid]-stk[0],A-stk[0])>0)r=mid-1;
        else l=mid+1;
      }
      return inside(A,stk[0],stk[r],stk[r+1]);
    }
    int w[105][105];
    int main(){
      int n,m;scanf("%d%d",&n,&m);
      for(int i=1;i<=n;++i)P1[i].read();
      for(int i=1;i<=m;++i)P2[i].read();
      convexhull(P1,n);
      for(int i=1;i<=m;++i){
        if(inside(P2[i]))P3[++cnt]=P2[i];    
      }
      if(cnt==0)printf("%d
    ",111*m);
      else{
        memset(w,0x3f,sizeof(w));
        for(int i=1;i<=n;++i){
          for(int j=1;j<=n;++j){
    	if(i!=j){
    	  bool flag=true;
    	  for(int k=1;k<=cnt;++k){
    	    if(cross(P1[j]-P1[i],P3[k]-P1[i])<0)flag=false;
    	  }
    	  if(flag)w[i][j]=1;
    	}
          }
        }
        for(int k=1;k<=n;++k){
          for(int i=1;i<=n;++i){
    	for(int j=1;j<=n;++j){
    	  if(w[i][k]+w[k][j]<w[i][j])w[i][j]=w[i][k]+w[k][j];
    	}
          }
        }
        int ans=0x3f3f3f3f;
        for(int i=1;i<=n;++i)if(w[i][i]<ans)ans=w[i][i];
        printf("%d
    ",20*ans+(m-cnt)*111);
      }
      return 0;
    }
    
    
  • 相关阅读:
    密码学复习
    Kafka Stream 高级应用
    Kafka Stream 流和状态
    Kafka Stream 处理器API
    SSM工作流程与原理详解
    Seata AT和XA模式
    分布式锁结合SpringCache
    使用RabbitMQ最终一致性库存解锁
    使用Springboot+SpringCloud+Seata1.3.0+Nacos1.2.1进行全局事务管理
    在微服务环境下,远程调用feign和异步线程存在请求数据丢失问题
  • 原文地址:https://www.cnblogs.com/liu-runda/p/7006898.html
Copyright © 2020-2023  润新知