usaco5.1.1 Fencing the Cows

一 原题

Fencing the Cows
Hal Burch

Farmer John wishes to build a fence to contain his cows, but he's a bit short on cash right. Any fence he builds must contain all of the favorite grazing spots for his cows. Given the location of these spots, determine the length of the shortest fence which encloses them.

PROGRAM NAME: fc

INPUT FORMAT

The first line of the input file contains one integer, N. N (0 <= N <= 10,000) is the number of grazing spots that Farmer john wishes to enclose. The next N line consists of two real numbers, Xi and Yi, corresponding to the location of the grazing spots in the plane (-1,000,000 <= Xi,Yi <= 1,000,000). The numbers will be in decimal format.

SAMPLE INPUT (file fc.in)

4
4 8
4 12
5 9.3
7 8

OUTPUT FORMAT

The output should consists of one real number, the length of fence required. The output should be accurate to two decimal places.

SAMPLE OUTPUT (file fc.out)

12.00



二 分析

裸的闭包。凭着回忆写的graham scan。忘记了发现叉乘结果为负就删除队尾元素这一过程是要递归进行的,前几次提交这一过程都只做了一次。。


三 代码

运行结果:
USER: Qi Shen [maxkibb3]
TASK: fc
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 4420 KB]
   Test 2: TEST OK [0.000 secs, 4420 KB]
   Test 3: TEST OK [0.000 secs, 4420 KB]
   Test 4: TEST OK [0.000 secs, 4420 KB]
   Test 5: TEST OK [0.011 secs, 4684 KB]
   Test 6: TEST OK [0.011 secs, 4816 KB]
   Test 7: TEST OK [0.011 secs, 5212 KB]
   Test 8: TEST OK [0.022 secs, 5872 KB]

All tests OK.

Your program ('fc') produced all correct answers! This is your submission #5 for this problem. Congratulations!


AC代码:
/*
ID:maxkibb3
LANG:C++
PROB:fc
*/

#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;

const int MAX = 10005;

int n;
int convex_size;

struct Coor {
    double x, y;
    double angle;
   
    Coor() {}
    Coor(double _x, double _y):x(_x),y(_y) {}
    
    Coor operator - (const Coor &obj) const {
        Coor *ret = new Coor(x - obj.x, y - obj.y);
        return *ret;
    }
    
    double dis(const Coor &obj) const {
        return sqrt((x - obj.x) * (x - obj.x) +
                    (y - obj.y) * (y - obj.y));
    }
    
    void set_angle(const Coor &obj) {
        if(x == obj.x && y == obj.y) {
            angle = MAX;
            return;
        }
        Coor v = *this - obj;
        angle =  v.x / dis(obj);
    }
}coor[MAX];
vector<Coor> convex;
Coor sc;

bool cmp(const Coor &a, const Coor &b) {
    if(a.angle == b.angle)
        return a.dis(sc) > b.dis(sc);
    return a.angle > b.angle;
}

void init() {
    freopen("fc.in", "r", stdin);
    freopen("fc.out", "w", stdout);
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%lf%lf", &coor[i].x, &coor[i].y);
        if(coor[i].y < sc.y ||
            (coor[i].y == sc.y && coor[i].x < sc.x))
            sc = coor[i];
    }
    for(int i = 0; i < n; i++) {
        coor[i].set_angle(sc);
    }
    sort(coor, coor + n, cmp);
}

double cross_product(Coor a, Coor b, Coor c) {
    Coor v1 = b - a;
    Coor v2 = c - b;
    return v1.x * v2.y - v1.y * v2.x;
}

void graham_scan() {
    if(n == 1) {
        convex.push_back(coor[0]);
        return;
    }
    convex.push_back(coor[0]);
    convex.push_back(coor[1]);
    convex_size = 2;
    for(int i = 2; i < n; i++) {
        while(cross_product(convex[convex_size - 2],
                        convex[convex_size - 1], coor[i]) <= 0) {  //这个地方没写成while,WA了好几次。。
            convex.pop_back();
            convex_size--;
        }
        convex.push_back(coor[i]);
        convex_size++;
    }
}

void solve() {
    graham_scan();
    double ans = 0;
    for(int i = 0; i < convex_size; i++)
        ans += convex[i].dis(convex[(i+1) % convex_size]);
    printf("%.2lf\n", ans);
}

int main() {
    init();
    solve();
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值