传送门


为了方便描述把固定点叫做白色点,Tree叫做黑色点

一种基于特殊性质的做法:

如果不算入选白色的权值,那么一定会选中所有白色点构成的凸包上的点,因为能够尽可能围更多的黑色点。然后我们在这个基础上删凸包上无用的白色点,就可以使得在围住尽可能多的黑色点的情况下白色点最少。

但是是否这就是最优解?我们考虑舍弃围住一个黑色点的情况。因为如果某个黑点在凸包中,那么一定存在三个凸包上的白色点,它们构成的三角形围住这个黑色点,使用三角剖分不难证明。所以舍弃一个黑色点最多只会舍弃三个白色点,而\(111 > 3 \times 20\),所以舍弃黑色点是不优的。

所以我们必须要在围住尽可能多的黑色点的情况下选择尽可能少的白色点。

我们认为凸包由其上所有点逆时针旋转构成,意味着对于一个向量\(i \rightarrow j\),如果它可能作为凸包的一部分,那么在上面求出的凸包中包含的所有黑点都在当前向量的左半平面内。

不妨设\(f_{i,j}=1\)表示向量\(i \rightarrow j\)可能作为凸包的一部分,那么我们要求的就是一个最小环,Floyd求最小环即可。

时间复杂度\(O(N^3)\),代码在下面


还有一种不基于\(20\)和\(111\)的DP做法

设\(f_{j,k}\)表示当前凸包中上凸包边界点为\(j\)、下凸包边界点为\(k\)时的最小权值,转移找到一个新的点\(l\):\(f_{j,l} = f_{j,k} + 20 - 111 * in_{j,k,l}\),其中\(in_{i,j,k}\)表示点\(i,j,k\)构成的三角形中黑点数量

算\(in_{i,j,k}\)只需要算\(num_{i,j}\)表示端点为点\(i,j\)的线段下端的黑点数量然后稍微容斥一下即可。

代码没有


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
//This code is written by Itst
using namespace std;

struct vec{
    int x , y;
    vec(int _x = 0 , int _y = 0) : x(_x) , y(_y){}
    vec operator +(vec a){return vec(x + a.x , y + a.y);}
    vec operator -(vec a){return vec(x - a.x , y - a.y);}
    int operator %(vec a){return x * a.y - y * a.x;}
    bool operator <(const vec a)const{return x < a.x || (x == a.x && y < a.y);}
}blk[107] , wht[107];
int stk[107] , ind[107] , floyd[107][107];
int N , M , top , cnt , sum;
bool in[107];

void create(){
    sort(blk + 1 , blk + N + 1);
    for(int i = 1 ; i <= N ; ++i){
        while(top > 1 && ((blk[i] - blk[stk[top - 1]]) % (blk[stk[top]] - blk[stk[top - 1]])) >= 0) --top;
        stk[++top] = i;
    }
    for(int i = 1 ; i <= top ; ++i) ind[++cnt] = stk[i];
    top = 0;
    for(int i = N ; i ; --i){
        while(top > 1 && ((blk[i] - blk[stk[top - 1]]) % (blk[stk[top]] - blk[stk[top - 1]])) >= 0) --top;
        stk[++top] = i;
    }
    for(int i = 2 ; i < top ; ++i) ind[++cnt] = stk[i];
    ind[++cnt] = ind[1];
}

void init(){
    for(int i = 1 ; i <= M ; ++i){
        bool f = 1;
        for(int j = 1 ; f && j < cnt ; ++j)
            f = (blk[ind[j + 1]] - blk[ind[j]]) % (wht[i] - blk[ind[j]]) > 0;
        if(!f) sum += 111;
        else in[i] = 1;
    }
}

bool check(int x , int y){
    for(int i = 1 ; i <= M ; ++i)
        if(in[i] && (blk[y] - blk[x]) % (wht[i] - blk[x]) < 0)
            return 0;
    return 1;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("C.in","r",stdin);
    freopen("C.out","w",stdout);
#endif
    cin >> N >> M;
    for(int i = 1 ; i <= N ; ++i) cin >> blk[i].x >> blk[i].y;
    for(int i = 1 ; i <= M ; ++i) cin >> wht[i].x >> wht[i].y;
    create(); init();
    if(sum == 111 * M){
        cout << sum;
        return 0;
    }
    memset(floyd , 1 , sizeof(floyd));
    for(int i = 1 ; i <= N ; ++i)
        for(int j = 1 ; j <= N ; ++j)
            if(i != j && check(i , j))
                floyd[i][j] = 1;
    int ans = 1e9;
    for(int i = 1 ; i <= N ; ++i)
        for(int j = 1 ; j <= N ; ++j)
            for(int k = 1 ; k <= N ; ++k)
                if(j != i && k != i)
                floyd[j][k] = min(floyd[j][k] , floyd[j][i] + floyd[i][k]);
    for(int i = 1 ; i <= N ; ++i) ans = min(ans , floyd[i][i]);
    cout << ans * 20 + sum;
    return 0;
}

BZOJ1390 CEOI2008 Fences 凸包、Floyd最小环/DP的更多相关文章

  1. HDU - 6080 :度度熊保护村庄 (凸包,floyd最小环)(VJ1900题达成)

    pro:二维平面上,给定N个村庄.M个士兵驻守,把村庄围住,现在我们想留下更多的士兵休息,使得剩下的士兵任然满足围住村庄.N,M<500: sol:即是要找一个最小的环,环把村庄围住. 由于是环 ...

  2. HDU 1599 find the mincost route (无向图floyd最小环详解)

    转载请注明出处:http://blog.csdn.net/a1dark 分析:终于弄懂了floyd的原理.以前的理解一直肤浅.所以一做到floyd应用的题.就拙计了.其实floyd的本质DP.利用前K ...

  3. ACM/ICPC 之 最短路-Floyd+SPFA(BFS)+DP(ZOJ1232)

    这是一道非常好的题目,融合了很多知识点. ZOJ1232-Adventrue of Super Mario 这一题折磨我挺长时间的,不过最后做出来非常开心啊,哇咔咔咔 题意就不累述了,注释有写,难点在 ...

  4. POJ 3311 Hie with the Pie(Floyd+状态压缩DP)

    题是看了这位的博客之后理解的,只不过我是又加了点简单的注释. 链接:http://blog.csdn.net/chinaczy/article/details/5890768 我还加了一些注释代码,对 ...

  5. hdoj 1599 find the mincost route【floyd+最小环】

    find the mincost route Time Limit: 1000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  6. POJ 1734.Sightseeing trip (Floyd 最小环)

    Floyd 最小环模板题 code /* floyd最小环,记录路径,时间复杂度O(n^3) 不能处理负环 */ #include <iostream> #include <cstr ...

  7. HDU1599(Floyd最小环)

    Floyd最小环理解+模板: https://www.cnblogs.com/DF-yimeng/p/8858184.html 除了上述博文里写的,我再补充几点我的理解. 1.为什么先枚举ij求经过i ...

  8. 【loj6177】「美团 CodeM 初赛 Round B」送外卖2 Floyd+状压dp

    题目描述 一张$n$个点$m$条边的有向图,通过每条边需要消耗时间,初始为$0$时刻,可以在某个点停留.有$q$个任务,每个任务要求在$l_i$或以后时刻到$s_i$接受任务,并在$r_i$或以前时刻 ...

  9. [poj3311]Hie with the Pie(Floyd+状态压缩DP)

    题意:tsp问题,经过图中所有的点并回到原点的最短距离. 解题关键:floyd+状态压缩dp,注意floyd时k必须在最外层 转移方程:$dp[S][i] = \min (dp[S \wedge (1 ...

随机推荐

  1. 自定义控件详解(六):Paint 画笔MaskFilter过滤

    首先看一个API:setMaskFilter(MaskFilter maskfilter): 设置MaskFilter,可以用不同的MaskFilter实现滤镜的效果,如滤化,立体等. 以下有两个Ma ...

  2. Kotlin入门(25)共享参数模板

    共享参数SharedPreferences是Android最简单的数据存储方式,常用于存取“Key-Value”键值对数据.在使用共享参数之前,要先调用getSharedPreferences方法声明 ...

  3. [Python][小知识][NO.4] wxPython 字体选择对话框(O.O 不知道放到那里就放到这个分类的)

    1.前言 O.O 前两天回家浪了两天,断更了 哎~~~ o.o 有时候,有木有想改标签或编辑框中内容的字体呀?(o.o 反正我是没有). wxpython也可以说是所在的操作系统,有字体选择器,给我们 ...

  4. 虚拟机中安装Virtualbox,嵌套的虚拟机不能运行64位系统

    https://www.quora.com/Can-I-install-Virtualbox-in-a-virtual-machine Here is a previous question on Q ...

  5. React router动态加载组件-适配器模式的应用

    前言 本文讲述怎么实现动态加载组件,并借此阐述适配器模式. 一.普通路由例子 import Center from 'page/center'; import Data from 'page/data ...

  6. 智能POS删除文件和数据库操作步骤

    1. 2. 3. 4.winbox:日志:winboxcash:数据库:winboxcyb:其他文件: 5.删除以上三个文件夹

  7. cookie 和session 的区别(转)

    二者的定义: 当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择, 都纪录下来.当下次你再光临同一个网站,WEB 服务器会先看看有 ...

  8. SSM 框架 ---项目整合

    一.SSM框架理解 Spring(业务层) Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象. Spring的核心思想是IoC(控 ...

  9. HTML 页面自动刷新

    学习就是一个不断积累的过程,每一天能够学到一点新东西说明自己就在进步!! HTML head 里面设置页面自动刷新功能 <meta http-equiv="Refresh" ...

  10. 让ie8支持 placeholder 属性

    一.  ie8支持 placeholder 属性 /* * ie8支持 placeholder 属性 */ $(function(){ if( !('placeholder' in document. ...