2010-02-03.ural1065-pku1758
这个题还是比较有意思的。
题目是要求在一个凸多边形中选几个点,要保证新组成的多边形包含m个景观点
题目中给出的凸多边形是按照顺时针顺序给出的,我们可以按照顺序找到合法的点的连接方法,然后转换成图论模型。
首先将题目中给出的点拷贝一份
p[0...n-1] 存的是原始的顺时针顺序给出的点
p[n...2n-1]是对上边的拷贝
然后
for (i = 0;i < n;i++) {
for (j = 1;j < n;j++) {
判断由p[i...i+j]组成的多变形是否包含景点。
其实也就是线段<p[i],p[j]> 是否有景点在左侧。
}
}
建图之后,由于点最多只有50个,完全可以用floyd求出所有点之间的最短距离,然后再枚举三角形
求出一个最短距离即可。
注意不能直接用floyd求出来的值dis[i][i]来找最短距离,因为会产生面积等于零的情况。
1
2 /*
3 * SOUR:ural1065 pku1758
4 * ALGO:computational and graph theory
5 * DATE:2010年 02月 01日 星期一 15:38:51 CST
6 * COMM:5//http://www.cppblog.com/schindlerlee/
7 * */
8 #include<iostream>
9 #include<cstdio>
10 #include<cstdlib>
11 #include<cstring>
12 #include<algorithm>
13 #include<cmath>
14 using namespace std;
15 typedef long long LL;
16 const int maxint = 0x7fffffff;
17 const long long max64 = 0x7fffffffffffffffll;
18 /*#define fprintf(x) while(0)*/
19 const int N = 128;
20 const int M = 2048;
21 int n,m, g[N][N];
22 struct point_t{
23 int x,y;
24 point_t(){}
25 point_t(int a,int b){x = a,y = b;}
26 }p[N],monu[M];
27 double dis[N][N];
28 point_t operator + (point_t a,point_t b) { return point_t(a.x + b.x,a.y + b.y);}
29 point_t operator - (point_t a,point_t b) { return point_t(a.x - b.x,a.y - b.y);}
30 int cross_mul(point_t a,point_t b) { return a.x * b.y - a.y * b.x;}
31 int dot_mul(point_t a,point_t b) { return a.x * b.x + a.y * b.y;}
32
33 bool judge(int beg,int end)
34 {
35 int i,j;
36 for (i = 0;i < m;i++) {
37 if (cross_mul(p[end]-p[beg],monu[i]-p[beg]) >= 0) {
38 return false;
39 }
40 }
41 return true;
42 }
43
44 void ckmin(double &a,double b) { if (a > b) { a = b; } }
45 #define sqr(x) ((x)*(x))
46 double dist(const point_t &a,const point_t &b) { return sqrt(0.0 + sqr(a.x-b.x) + sqr(a.y-b.y)); }
47
48 int main()
49 {
50 int i,j,k;
51 scanf("%d%d",&n,&m);
52 for (i = 0;i < n;i++) { scanf("%d %d",&p[i].x,&p[i].y); p[i+n] = p[i]; }
53 for (i = 0;i < m;i++) { scanf("%d %d",&monu[i].x,&monu[i].y); }
54 for (i = 0;i < n;i++) {
55 for (j = 1;j < n;j++) {
56 if (judge(i,i+j)) {
57 g[i][(i+j)%n] = 1;
58 }
59 }
60 }
61
62 for (i = 0;i < n;i++) {
63 for (j = 0;j < n;j++) {
64 if (g[i][j]) {
65 dis[i][j] = dist(p[i],p[j]);
66 }else if(i == j){
67 dis[i][j] = 0;
68 }else {
69 dis[i][j] = maxint;
70 }
71 }
72 }
73
74 //floyd
75 for (k = 0;k < n;k++) {
76 for (i = 0;i < n;i++) {
77 for (j = 0;j < n;j++) {
78 ckmin(dis[i][j],dis[i][k]+dis[k][j]);
79 }
80 }
81 }
82
83 //这么写完全是为了保证面积不为0
84 double res = maxint;
85 for (k = 0;k < n;k++) {
86 for (i = 0;i < n;i++) {
87 for (j = 0;j < n;j++) {
88 if (res > dis[i][j] + dis[j][k] + dis[k][i] && cross_mul(p[i]-p[k],p[j]-p[k]) != 0) {
89 res = dis[i][j] + dis[j][k] + dis[k][i];
90 }
91 }
92 }
93 }
94
95 printf("%.2f\n",res);
96 return 0;
97 }
98