Why so serious? --[NKU]schindlerlee

2010-02-03.ural1065-pku1758

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 


posted on 2010-02-03 17:41 schindlerlee 阅读(936) 评论(0)  编辑 收藏 引用 所属分类: 解题报告


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理