zoukankan      html  css  js  c++  java
  • GYM

    题意:

      长和宽分别为M+N/2,N的矩形中。有很多敌人的点。有两种方法消灭敌人。

      1.N个桶,第i个桶可以消灭i-1<=x<i中的敌人。2.M个摆(半圆)每个摆可以消灭距离他前面不超过1以内的敌人。第i个摆的圆心在(N/2,i-1),半径都为N/2。

      问消灭所有敌人消耗的最少设备是多少。

    题解:

      根据题意可以发现,每一个敌人都可以被桶消灭,但不一定被摆消灭。摆的盲区在第1个摆的内部和第M个摆两边的死角位置。

      所以出现在盲区的点必须被桶消灭。即那些桶是必选的。

      其余的点把消灭他的桶号和消灭他的摆号连边,跑一个最小顶点覆盖即可。

    #include <bits/stdc++.h>
    using namespace std;
    int t;
    int p;
    double n, m;
    int ans;
    int vp[10005];
    int vis[205];
    int match[205];
    struct ndoe {
        double x, y;
    }w[10005];
    double distance(double x1, double y1, double x2, double y2) {
        return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    }
    vector<int> g[205];
    bool dfs(int u) {
        for(int i = 0; i < g[u].size(); i++) {
            int v = g[u][i], w = match[v];
            if(vis[v]) continue;
            vis[v] = 1;
            if(w<0 || dfs(w)) {
                match[v] = u;
                return true;
            }
        }
        return false;
    }
    int hungarian() {
        int res = 0;
        memset(match, -1, sizeof(match));
        for(int u = 0; u < n; u++) {
            memset(vis, 0, sizeof(vis));
            if(dfs(u)) res++;
        }
        return res;
    }
    int main() {
        freopen("wall.in","r",stdin);
        scanf("%d", &t);
        while(t--) {
            ans = 0;
            memset(vp, 0, sizeof(vp));
            scanf("%lf%lf%d", &n, &m, &p);
            for(int i = 0; i < n+m; i++) g[i].clear();
            for(int i = 1; i <= p; i++) scanf("%lf%lf", &w[i].x, &w[i].y);
            memset(vis, 0, sizeof(vis));
            for(int i = 1; i <= p; i++) {
                if(distance(n/2, 0, w[i].x, w[i].y)<=n/2 || (w[i].y>m && distance(n/2, m-1, w[i].x, w[i].y)>1.0+n/2)) {
                    vp[i] = 1;
                    int v = (int)floor(w[i].x);
                    if(vis[v]) continue;
                    else {
                        vis[v] = 1; ans++;
                    }
                }
            }
            for(int i = 1; i <= p; i++) {
                if(vp[i]) continue;
                int judge = (int)floor(w[i].x);
                if(vis[judge]) continue;
                int up = (int)floor(w[i].y);
                for(int v = up; v >= 0; v--) {
                    if(distance(n/2, (double)v, w[i].x, w[i].y) > n/2) {
                        int u = (int)floor(w[i].x);
                        g[u].push_back(v+n); 
                        break;
                    }
                }
            }
            ans += hungarian();
            printf("%d
    ", ans);
        }
    } 
    View Code
  • 相关阅读:
    [LeetCode] Implement Stack using Queues
    [LeetCode] String Compression
    [国嵌攻略][060][LCD工作原理解析]
    [国嵌攻略][059][2440-DMA程序设计]
    [国嵌攻略][057][串口控制台建立]
    [国嵌攻略][056][串口驱动程序设计]
    [国嵌攻略][054][NandFlash驱动设计_写]
    [问题笔记][指针相加翻译成汇编右移2位]
    [国嵌攻略][053][6410和210按键中断编程]
    [国嵌攻略][050][2440按键中断编程]
  • 原文地址:https://www.cnblogs.com/Pneuis/p/8900758.html
Copyright © 2011-2022 走看看