关闭

POJ 1873 The Fortified Forest 凸包+枚举

560人阅读 评论(0) 收藏 举报

题意:一个人有好多树,这些树有坐标,有价值,以及砍下这颗树能造多长的篱笆。

现在他要保护自己的树不被别人砍,就需要用篱笆把树围起来,但是需要从自己的树中砍下来几棵树造成篱笆,所以问题就来了,如何砍最少价值的树把剩余的树围起来。如果价值一样,就找砍树数量少的。


看到这道题的数据范围我就笑了,直接指数级别的枚举就行了。然后求凸包。


/*
ID: sdj22251
PROG: subset
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define MAXN 1111111
#define MAXM 104444
#define INF 100000000
#define eps 1e-7
#define L(X) X<<1
#define R(X) X<<1|1
using namespace std;
typedef double T;
struct POINT
{
  T x;
  T y;
  POINT() : x(0), y(0) {};
  POINT(T _x_, T _y_) : x(_x_), y(_y_) {};
};
POINT p[555], s[555];
T x[555], y[555],  l[555];
int v[555];
T DIS(const POINT & a, const POINT & b)
{
  return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
T CROSS(const POINT & a, const POINT & b, const POINT & o)
{
  return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
}
bool cmp(const POINT & A, const POINT & B)
{
    T CR = CROSS(A, B, p[0]);
    if(CR > 0) return true;
    if(CR == 0) return DIS(A, p[0]) < DIS(B, p[0]);
    return false;
}
struct ant
{
    int a[18];
    int cnt, v;
    double len;
    void init(){ cnt = 0; len = 0; v = 0;}
};
int main()
{
    int n;
    int cas = 0;
    while(scanf("%d", &n) != EOF && n)
    {
        if(cas) printf("\n");
        for(int i = 0; i < n; i++)
            scanf("%lf%lf%d%lf", &x[i], &y[i], &v[i], &l[i]);
        int bd = (1 << n);
        ant ans;
        ans.init();
        ans.v = INF;
        T fk = 0;
        for(int j = 0; j < bd; j++)
        {
            int cnt = 0;
            int ti = j;
            ant tx;
            tx.init();
            int tn = 0;
            double need = 0;
            while(cnt < n)
            {
                if(ti & 1)
                {
                    tx.a[tx.cnt ++] = cnt;
                    tx.len += l[cnt];
                    tx.v += v[cnt];
                }
                else
                {
                    p[tn].x = x[cnt];
                    p[tn++].y = y[cnt];
                    need += l[cnt];
                }
                ti >>= 1;
                cnt++;
            }
            T xx = INF, yy = INF;
            int tmp;
            //for(int i = 0; i < tx.cnt; i++)
            //printf("%d ", tx.a[i]);
            //printf("\n");
            for(int i = 0; i < tn; i++)
            {
                //printf("ss %.3f %.3f\n", p[i].x, p[i].y);
                if(p[i].x < xx || p[i].x == xx && p[i].y < yy)
                {
                    xx = p[i].x;
                    yy = p[i].y;
                    tmp = i;
                }
            }
            double cir = 0;
            if(tn == 0 || tn == 1) cir = 0;
            else if(tn == 2)  cir = 2.0 *sqrt(DIS(p[0], p[1]));
            else{
                int top;
                swap(p[0], p[tmp]);
                sort(p + 1, p + tn, cmp);
                s[0] = p[0];
                s[1] = p[1];
                s[2] = p[2];
                top = 2;
                for(int i = 3; i < tn; i++)
                {
                    while(CROSS(p[i], s[top], s[top - 1]) > 0 && top > 1)
                    top--;
                    s[++top] = p[i];
                }
                for(int i = 0; i < top; i++)
                        cir +=sqrt(DIS(s[i], s[i + 1]));
                cir += sqrt(DIS(s[0], s[top]));
            }
            if(tx.len - cir > eps)
            {
                if(ans.v > tx.v)
                {
                    ans = tx;
                    fk = tx.len - cir;
                }
                else if(ans.v  == tx.v && ans.cnt > tx.cnt)
                {
                    ans = tx;
                    fk = tx.len - cir;
                }
            }
        }
        printf("Forest %d\nCut these trees:", ++cas);
        for(int i = 0; i < ans.cnt; i++)
        printf(" %d", ans.a[i] + 1);
        printf("\nExtra wood: %.2f\n", fk);
    }
    return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:620666次
    • 积分:10622
    • 等级:
    • 排名:第1590名
    • 原创:438篇
    • 转载:3篇
    • 译文:0篇
    • 评论:87条
    最新评论