BZOJ1390 CEOI2008 Fences 凸包、Floyd最小环/DP

news/2024/11/9 23:23:43

传送门


为了方便描述把固定点叫做白色点,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;
}

转载于:https://www.cnblogs.com/Itst/p/10484782.html


http://www.niftyadmin.cn/n/529816.html

相关文章

respond.php,respond.php

//WEBSC商城资源define(IN_ECS, true);require dirname(__FILE__) . /includes/init.php;require ROOT_PATH . includes/lib_payment.php;require ROOT_PATH . includes/lib_order.php;$pay_code (!empty($_REQUEST[code]) ? trim($_REQUEST[code]) : );if (empty($pay_code)…

javascript检测flash版本

今天要做一个根据用户安装的是什么flash版本&#xff0c;为其播放哪断视频&#xff0c;所以搜了先用javaScrip检测出来版本后&#xff0c;再将其参数发给flash&#xff0c; <SCRIPT typetext/javascript><!--var i_flash;var v_flash;// Netscape if (navigator.plugi…

php 静态方法调用成员,PHP静态方法在成员变量中使用命名空间调用

是不是可以在PHP中做这样的事情&#xff1f;我想在一个成员变量中有一个名称空间,并且总是能够调用该类的每个静态方法,就像我在下面所做的那样.当然我的代码不起作用,但我只是想知道这是否可行,并且我接近解决方案,或者如果这完全不可能并且必须始终使用语法&#xff1a;\Stri…

注入(Injection)

注入(Injection)是: Java EE提供了注入机制&#xff0c;使您的对象能够获取对资源和其他依赖项的引用&#xff0c;而无需直接实例化它们。通过使用将字段标记为注入点的注释之一来装饰字段或方法&#xff0c;可以在类中声明所需的资源和其他依赖项。然后容器在运行时提供所需的…

javaScript 测试下载速度

<script>function init(){var timer1new Date().getTime();var imgnew Image();img.src"http://www.netfront.net/speedtest/images/photo" parseInt(Math.round(Math.random()*5)1) ".bmp?" Math.random();img.οnlοadfunction(){sizeimg.file…

CMDB学习之六 --客户端请求测试,服务端api优化

客户端使用agent 请求测试&#xff0c;agent使用的POST 请求&#xff0c;使用requests模块 本地采集&#xff0c;汇报服务端 #!/usr/bin/env python # -*- coding:utf-8 -*- from .base import BaseHandler from ..plugins import get_server_info import requests import json…

FLEX杂谈——flex就业现状与学习标准分析

写下这个标题大家一定以为我是只FLEX老鸟,不然不敢这么高声说话,而且是在JAVAEYE里.我知道JE里高手很多.有很多人都对FLEX有秀深的见底,写此文是为了回答一些朋友对我的提问. 有很多想转行的开发者都问我这样几个问题:现在招FLEX的公司多吗?搞FLEX开发工资高吗?怎么样才算是F…

php的 提示无效字符,PHP无效字符错误

运行此代码时出现此错误&#xff1a;致命错误&#xff1a;test.php中带有消息’无效字符错误’的未捕获异常’DOMException’&#xff1a;29堆栈跟踪&#xff1a;#0 test.php(29)&#xff1a;DOMDocument-> createElement(‘1OhmStable’,’a’)#1 { main}在第29行的test.ph…