• 2017"百度之星"程序设计大赛


    Problem Description
    哗啦啦村袭击了喵哈哈村!

    度度熊为了拯救喵哈哈村,带着自己的伙伴去救援喵哈哈村去了!度度熊与伙伴们很快的就过来占据了喵哈哈村的各个军事要地,牢牢的守住了喵哈哈村。

    但是度度熊发现,这是一场旷日持久的战斗,所以度度熊决定要以逸待劳,保存尽量多的体力,去迎战哗啦啦村的战士。

    于是度度熊决定派尽量多的人去休息,但是同时也不能松懈对喵哈哈村的保护。

    换句话而言,度度熊希望尽量多的人休息,而且存在一个包围圈由剩下的人组成,且能够恰好的包围住喵哈哈村的所有住房(包括边界)。

    请问最多能让多少个人休息呢?
     
    Input
    本题包含若干组测试数据。

    第一行一个整数n,表示喵哈哈村的住房数量。

    接下来n行,每行两个整数(x1[i],y1[i]),表示喵哈哈村的住房坐标。

    第n+1行一个整数m,表示度度熊的士兵数量。

    接下来m行,每行两个整数(x2[i],y2[i]),表示度度熊伙伴的坐标。

    满足:

    1<=n,m<=500

    -10000<=x1[i],x2[i],y1[i],y2[i]<=10000
     
    Output
    请输出最多的人员休息的数目。

    如果无法保护整个村庄的话,输出"ToT"
     
    Sample Input
    2
    1 1
    2 2
    4
    0 0
    0 4
    4 2
    4 0
    1
    1 1
    2
    0 0
    0 1
     
    Sample Output
    1
    ToT
     
    网上看到一中方法,度度熊的士兵数量有m个,喵哈哈村的住房数量有n个,假设n个住房全在度度熊伙伴 i--j 的右侧或者线上,则 i 到 j 连接一条长度为1的单向边。
    之后就可以得到一张图了,其中最小的环就是最优方案,G[i][j]是从 i 到 j 的最短路。那么最大的m-G[i][i]就是答案了。
    当然要考虑没有的应该。
     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <algorithm>
     5 #define INF 0x3f3f3f3f
     6 using namespace std;
     7 const int N = 550;
     8 struct Point {
     9     int x, y;
    10 };
    11 int n, m, G[N][N];
    12 Point a[N], b[N];
    13 int mymin (int x,int y){return x<y?x:y;}
    14 bool check(Point a, Point b, Point c) {
    15     if(a.x > b.x && a.x > c.x) return true;
    16     if(a.x < b.x && a.x < c.x) return true;
    17     if(a.y < b.y && a.y < c.y) return true;
    18     if(a.y > b.y && a.y > c.y) return true;
    19     return false;
    20 }
    21 double fun(Point a, Point b, Point c) {
    22     double x1 = a.x - c.x, y1 = a.y - c.y;
    23     double x2 = b.x - c.x, y2 = b.y - c.y;
    24     return x1 * y2 - x2 * y1;
    25 }
    26 int main() {
    27     while(scanf("%d", &n) != EOF) {
    28         for(int i = 1; i <= n; i ++) {
    29             scanf("%d %d", &a[i].x, &a[i].y);
    30         }
    31         scanf("%d", &m);
    32         for(int i = 1; i <= m; i ++) {
    33             scanf("%d %d", &b[i].x, &b[i].y);
    34         }
    35         for(int i = 1; i <= m; i ++) {
    36             for(int j = 1; j <= m; j ++) {
    37                 G[i][j] = INF;
    38             }
    39         }
    40         for(int i = 1; i <= m; i ++) {
    41             for(int j = 1; j <= m; j ++) {
    42                 bool flag = true;
    43                 for(int k = 1; k <= n; k ++) {
    44                     if(fun(a[k], b[j], b[i]) < 0) flag = false;
    45                     if(fun(a[k], b[j], b[i]) == 0 && check(a[k], b[j], b[i])) flag = false;
    46                     if(!flag) break;
    47                 }
    48                 if(flag) G[i][j] = 1;
    49             }
    50         }
    51         for(int i = 1; i <= m; i ++) {
    52             for(int j = 1; j <= m; j ++) {
    53                 if(G[j][i] == INF) continue;
    54                 for(int k = 1; k <= m; k ++) {
    55                     G[j][k] = mymin(G[j][k], G[j][i] + G[i][k]);
    56                 }
    57             }
    58         }
    59         int ans = INF;
    60         for(int i = 1; i <= m; i ++) {
    61             ans = mymin(ans, G[i][i]);
    62         }
    63         if(ans > m) printf("ToT
    ");
    64         else printf("%d
    ",m - ans);
    65     }
    66     return 0;
    67 }

    不过我做的有点复杂了,先是用m个点建立一个凸包,然后判断n个点是否都在凸包内,然后一个for循环每次从m中删除一个点重新建立一个凸包,看能否包含n个点,不能的话就不删除,能的话肯定删除掉。

    但是答案一直错误。。。。。代码先放这。

      1 #include <iostream>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <stdio.h>
      5 #include <vector>
      6 using namespace std;
      7 const int N = 550;
      8 double EPS = 1e-10;
      9 int n, m, ans, cnt;
     10 // double add(double a,double b) {
     11 //     if(abs(a+b) < EPS * (abs(a) + abs(b))) return 0;
     12 //     return a + b;
     13 // }
     14 struct Point{
     15     int x, y;
     16     Point(){}
     17     Point(int x, int y) :x(x), y(y) {}
     18     Point operator + (Point p) {
     19         return Point(x + p.x, y + p.y);
     20     }
     21     Point operator - (Point p) {
     22         return Point(x - p.x, y - p.y);
     23     }
     24     Point operator * (int d) {
     25         return Point(x*d, y*d);
     26     }
     27     int dot(Point p) {    //内积
     28         return x * p.x + y * p.y;
     29     }
     30     int det(Point p) {    //外积
     31         return x * p.y - y * p.x;
     32     }
     33 };
     34 Point qs[N], qu[N];
     35 bool vis[N];
     36 vector<Point> ps;
     37 bool cmp(Point x, Point y) {
     38     if(x.x != y.x) return x.x < y.x;
     39     else return x.y < y.y;
     40 }
     41 vector<Point> convex_hull(Point *ps, int n) {
     42     sort(ps, ps+n, cmp);
     43     int k = 0;
     44     vector<Point> qs(n*2);
     45     for(int i = 0; i < n; i ++) {   //下侧
     46         if(vis[i])continue;
     47         while(k > 1 && (qs[k-1] - qs[k-2]).det(ps[i] - qs[k-1]) <= 0) k--;
     48         qs[k++] = ps[i];
     49     }
     50     for(int i = n-2, t = k; i >= 0; i --) { //上侧
     51         if(vis[i])continue;
     52         while(k > t && (qs[k-1] - qs[k-2]).det(ps[i] - qs[k-1]) <= 0) k--;
     53         qs[k++] = ps[i];
     54     }
     55     cnt = k-1;
     56     qs.resize(k-1);
     57     return qs;
     58 }
     59 bool check() {
     60     for(int i = 0; i < n; i ++) {
     61         if(m - ans == 1) {
     62             if(qs[i].x != ps[0].x || qs[i].y != ps[0].y) return false;
     63         } else if(m - ans == 2){
     64             if((qs[i] - ps[0]).det(ps[1] - qs[i]) !=  0) return false;
     65         } else {
     66             for(int j = 0; j < cnt; j ++) {
     67                 if((qs[i] - ps[j]).det(ps[(j+1)%cnt] - qs[i]) > 0) {
     68                     // printf("%d %d
    ",(qs[i] - ps[j]).x,(qs[i] - ps[j]).y);
     69                     // printf("%d %d
    ",(qs[i] - ps[j]).x,(qs[i] - ps[j]).y);
     70                     // printf("%d ++
    ",(qs[i] - ps[j]).det(ps[(j+1)%cnt] - qs[i]) );
     71                     // printf("%d  %d
    ",i,j);
     72                     return false;
     73                 }
     74             }
     75         }
     76     }
     77     return true;
     78 }
     79 int main() {
     80     while(scanf("%d",&n) != EOF) {
     81         memset(vis, false, sizeof(vis));
     82         ans = 0;
     83         for(int i = 0; i < n; i ++) {
     84             scanf("%d %d", &qs[i].x, &qs[i].y);
     85         }
     86         scanf("%d", &m);
     87         for(int i = 0; i < m; i ++) {
     88             scanf("%d %d", &qu[i].x, &qu[i].y);
     89         }
     90         ps = convex_hull(qu, m);
     91         // for(int i = 0; i < ps.size(); i ++) {
     92         //     printf("%d %d
    ",ps[i].x, ps[i].y);
     93         // }
     94         if(!check()) {
     95             printf("ToT
    ");
     96             continue;
     97         }
     98         for(int i = 0; i < m; i ++) {
     99             if(m - ans == 1)break;
    100             vis[i] = true;
    101             ps.clear();
    102             ps = convex_hull(qu, m);
    103             if(check()) {
    104                 ans ++;
    105                 continue;
    106             }
    107             else vis[i] = false;
    108         }
    109         printf("%d
    ",ans);
    110         ps.clear();
    111     }
    112     return 0;
    113 }
    View Code
  • 相关阅读:
    双向链表的创建,查找,删除
    atoi 函数自实现
    strcmp,strcpy,strcat,strncmp,strncpy,strncat,自实现精炼版本
    天生棋局(堆上申请二维空间的应用)
    使用二级指针,初始化一级指针
    指针数组的简单理解
    输入二进制数,输出10进制数
    阶乘循环联系题
    [剑指offer] 二叉搜索树的第k个节点
    二叉树的序列化和反序列化
  • 原文地址:https://www.cnblogs.com/xingkongyihao/p/7301420.html
Copyright © 2020-2023  润新知