zoukankan      html  css  js  c++  java
  • POJ 1873 The Fortified Forest

    POJ_1873

        由于树木比较少,可以枚举砍树的决策,然后计算砍掉的树木的长度是否比剩下的树木的凸包的周长要长,每次计算之后按题意更新最优解即可。

        在枚举的时候还可以应用一个剪枝,就是如果当前砍树损失的价值比记录的最小价值要大的话,就可以直接枚举下一种情况了,而不必再去花时间计算凸包和凸包的周长了,这样可以节省很多时间。

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<stdlib.h>
    #define MAXD 20
    #define zero 1e-8
    #define INF 0x3f3f3f3f
    struct point
    {
    int x, y;
    }p[MAXD], res[MAXD], q[MAXD];
    int st, N, X, P, num, minv, v[MAXD];
    double w[MAXD], ans;
    int cmp(const void *_p, const void *_q)
    {
    point *p = (point *)_p, *q = (point *)_q;
    if(p->y == q->y)
    return p->x - q->x;
    return p->y - q->y;
    }
    int dcmp(double x)
    {
    return fabs(x) < 0 ? 0 : (x < 0 ? -1 : 1);
    }
    double sqr(double x)
    {
    return x * x;
    }
    int det(int x1, int y1, int x2, int y2)
    {
    return x1 * y2 - x2 * y1;
    }
    void init()
    {
    int i, j, k;
    for(i = 0; i < N; i ++)
    scanf("%d%d%d%lf", &p[i].x, &p[i].y, &v[i], &w[i]);
    }
    int del(int top, int i)
    {
    if(det(res[top].x - res[top - 1].x, res[top].y - res[top - 1].y, q[i].x - res[top].x, q[i].y - res[top].y) <= 0)
    return 1;
    return 0;
    }
    int graham()
    {
    int i, j, k, top = 1, mint;
    qsort(q, X, sizeof(q[0]), cmp);
    res[0] = q[0], res[1] = q[1];
    for(i = 2; i < X; i ++)
    {
    while(top && del(top, i))
    -- top;
    res[++ top] = q[i];
    }
    mint = top;
    res[++ top] = q[X - 2];
    for(i = X - 3; i >= 0; i --)
    {
    while(top != mint && del(top, i))
    -- top;
    res[++ top] = q[i];
    }
    return top;
    }
    double calculate()
    {
    int i, j, k;
    double t;
    if(X == 1)
    t = 0;
    else if(X == 2)
    t = 2 * sqrt(sqr(q[0].x - q[1].x) + sqr(q[0].y - q[1].y));
    else
    {
    P = graham();
    t = 0;
    for(i = 0; i < P; i ++)
    t += sqrt(sqr(res[i].x - res[i + 1].x) + sqr(res[i].y - res[i + 1].y));
    }
    return t;
    }
    void solve()
    {
    int i, j, k, cnt, value;
    double t, s;
    minv = num = INF;
    for(k = 1; k < (1 << N); k ++)
    {
    s = cnt = value = X = 0;
    for(j = 0; j < N; j ++)
    {
    if((1 << j) & k)
    {
    ++ cnt;
    value += v[j];
    s += w[j];
    }
    else
    q[X ++] = p[j];
    }
    if(value > minv)
    continue;
    t = calculate();
    if(dcmp(s - t) < 0)
    continue;
    if(value < minv || (value == minv && cnt < num))
    {
    minv = value;
    num = cnt;
    st = k;
    ans = s - t;
    }
    }
    printf("Cut these trees:");
    for(i = 0; i < N; i ++)
    if((1 << i) & st)
    printf(" %d", i + 1);
    printf("\n");
    printf("Extra wood: %.2lf\n", ans);
    }
    int main()
    {
    int t = 0;
    for(;;)
    {
    scanf("%d", &N);
    if(!N)
    break;
    init();
    if(t ++)
    printf("\n");
    printf("Forest %d\n", t);
    solve();
    }
    return 0;
    }


  • 相关阅读:
    转 Java高级程序员面试题
    发个说说0.0
    SpringMvc和servlet对比
    java面试数据类型
    java面试 关键字
    Ajax与传统Web开发的区别
    ssm框架常见问题
    浅谈C++多态性
    [转载]构造函数、析构函数可否声明为虚函数
    为什么不要在构造函数和析构函数中调用虚函数?
  • 原文地址:https://www.cnblogs.com/staginner/p/2357674.html
Copyright © 2011-2022 走看看