zoukankan      html  css  js  c++  java
  • bzoj 1390: [Ceoi2008]Fence

    Description

    在一个大小为1000*1000的区域中,有n个固定点,m棵tree 。 现在你要建一个围栏来保护tree,建它的费用为你选用的固定点的个数 *20和 你没有圈进围栏的tree*111. 现在希望这个值越小越好. 3<=N<=100. 1<=M<=100

    Input

    第一行给出n,m 下面开始n行,给出固定的坐标 下面开始m行,给出tree的坐标

    Output

    输出最小费用

    根据题目设定的参数,凡是可以围住的点都要围住,同bzoj1027可以转为最小环

    #include<bits/stdc++.h>
    struct pos{
        int x,y;
        void read(){
            scanf("%d%d",&x,&y);
        }
    }ns[107],ms[107],cs[107];
    pos operator-(pos a,pos b){return (pos){a.x-b.x,a.y-b.y};}
    int operator*(pos a,pos b){return a.x*b.y-a.y*b.x;}
    bool operator<(pos a,pos b){return a*b<0;}
    int ans=0,n,m,cp=0;
    bool in(pos w){
        for(int i=2;i<cp;++i)if(cs[i-1]<w&&w<cs[i]){
            return cs[i-1]-w<cs[i]-w;
        }
        return 0;
    }
    void mins(int&a,int b){if(a>b)a=b;}
    int l[107][107];
    char s[107][107];
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;++i)ns[i].read();
        for(int i=0;i<m;++i)ms[i].read();
        for(int i=1;i<n;++i)if(ns[i].x<ns[0].x)std::swap(ns[i],ns[0]);
        pos p0=ns[0];
        for(int i=0;i<n;++i)ns[i]=ns[i]-p0;
        for(int i=0;i<m;++i)ms[i]=ms[i]-p0;
        std::sort(ns+1,ns+n);
        for(int i=0;i<n;++i){
            while(cp>=2&&ns[i]-cs[cp-1]<cs[cp-1]-cs[cp-2])--cp;
            cs[cp++]=ns[i];
        }
        int p=0;
        for(int i=0;i<m;++i){
            if(!in(ms[i]))ans+=111;
            else ms[p++]=ms[i];
        }
        m=p;
        if(p){
            for(int i=0;i<n;++i){
                for(int j=0;j<n;++j){
                    l[i][j]=0x3f3f3f3f;
                    if(i!=j){
                        bool is=1;
                        pos d=ns[i]-ns[j];
                        for(int k=0;k<m;++k)if(d<ms[k]-ns[j]){
                            is=0;
                            break;
                        }
                        if(is)l[i][j]=1;
                    }
                }
            }
            for(int k=0;k<n;++k)
                for(int i=0;i<n;++i)
                    for(int j=0;j<n;++j)mins(l[i][j],l[i][k]+l[k][j]);
            for(int i=1;i<n;++i)mins(l[0][0],l[i][i]);
            ans+=l[0][0]*20;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Servlet的几种跳转(转)
    Java String.split()用法小结(转)
    表单数据提交的方法
    gedit文本编辑器乱码解决办法
    J-Link烧写bootloader到mini2440的Nor Flash
    虚拟机安装Fedora10系统遇到异常
    linux系统忘记root密码怎么办?
    编译busybox时出错及解决方案
    source insight代码查看器如何自定义添加文件类型
    < Objective-C >文件操作-NSFileHandle
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7162646.html
Copyright © 2011-2022 走看看