题目大意求一旋转向内的连线,可以想象成蜗牛的壳
不得不说这个我弄的狠纠结,一开是用的Graham,带上模板,一WA到死,怒了,代码全删了,自己看过包裹法,又认真看了遍叉积,点积,自己写了个只用叉积的算法。
算法思路:
step 1: 第一次取y最小,y相等取x最小的点。p0
step 2: 每次取第一个未标记的点pk,尝试拓展 p0-pk ,若发现存在pi 使得 p0-pi 在p0-pk 的左边(他们的叉积 < 0),则 k = i ;
step 3: 重复执行step 2,直到取得所有点
参考代码:
HOJ 1696
1 struct POINT {
2 int x,y;
3 int idx;
4 bool mark;
5 POINT(int i,int a,int b) {
6 idx=i;x=a;y=b;mark=false;
7 }
8 POINT(){}
9 }p[MAXN],res[MAXN];
10
11 int n,idx;
12
13 inline double multiply(POINT o,POINT s,POINT e) {
14 return ((s.x - o.x) * (e.y - o.y) - (s.y - o.y) * (e.x - o.x));
15 }
16
17
18 void ground() {
19 int cnt = 0;
20 for(int i = 1;i<n;i++) {
21 if(p[i].y < p[0].y ||
22 ((p[i].y == p[0].y) &&
23 (p[i].x < p[0].x)))
24 swap(p[0],p[i]);
25 }
26 res[cnt++] = p[0];
27 p[0].mark = true;
28 while(cnt < n) {
29 int k = 0;
30 for(int i = 0;i<n;i++) {
31 if(!p[i].mark) {
32 k = i;
33 break;
34 }
35 }
36 for(int i = k + 1;i<n;i++) {
37 if(!p[i].mark) {
38 if(multiply(res[cnt-1],p[k],p[i]) < 0)
39 k = i;
40 }
41 }
42 res[cnt++] = p[k];
43 p[k].mark = true;
44 }
45 }
46
47 void init() {
48 SCF(n);
49 int id,a,b;
50 F(i,n) {
51 SCFT(id,a,b);
52 p[i] = POINT(id,a,b);
53 }
54 ground();
55 PCF(n);
56 F(i,n) printf(" %d",res[i].idx);
57 puts("");
58 }
59
60
61 int main() {
62 FOPEN;
63 int cse;SCF(cse);
64 while(cse --) {
65 init();
66 }
67 }