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
第一行一个整数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"
如果无法保护整个村庄的话,输出"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 }