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\n");
64         else printf("%d\n",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\n",(qs[i] - ps[j]).x,(qs[i] - ps[j]).y);
 69                     // printf("%d %d\n",(qs[i] - ps[j]).x,(qs[i] - ps[j]).y);
 70                     // printf("%d ++\n",(qs[i] - ps[j]).det(ps[(j+1)%cnt] - qs[i]) );
 71                     // printf("%d  %d\n",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\n",ps[i].x, ps[i].y);
 93         // }
 94         if(!check()) {
 95             printf("ToT\n");
 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\n",ans);
110         ps.clear();
111     }
112     return 0;
113 }
View Code

 

posted @ 2017-08-07 21:27  starry_sky  阅读(756)  评论(1编辑  收藏  举报