zoukankan      html  css  js  c++  java
  • POJ 1873 /// 状压+凸包

    题目大意:

    国王有一片森林,巫师需要从所有树中选出一些做成围栏把其他树围起来,

    每棵树都有其对应的价值 v 和能作为围栏的长度 l

    要求最小价值,若存在多种最小价值的方案则选择余下长度更少的

    树木较少 状态压缩 枚举所有状态

    计算当前的状态 被选中的 树的价值和长度

    其他 被围起来(未被选中)的树去求凸包

    计算凸包的边长(即围栏的最小长度)

    判断选中的树是否能围住凸包 再更新答案

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #define INF 0x3f3f3f3f
    using namespace std;
    
    const double eps=1e-10;
    double add(double a,double b) {
        if(abs(a+b)<eps*(abs(a)+abs(b))) return 0;
        return a+b;
    }
    struct P {
        double x,y;
        P(){};
        P(double _x,double _y):x(_x),y(_y){};
        P operator - (P p) {
            return P(add(x,-p.x),add(y,-p.y)); }
        P operator + (P p) {
            return P(add(x,p.x),add(y,p.y)); }
        P operator * (double d) {
            return P(x*d,y*d); }
        double dot(P p) {
            return add(x*p.x,y*p.y); }
        double det(P p) {
            return add(x*p.y,-y*p.x); }
    }p1[20], p2[20], p3[20];
    int n;
    double v[20], l[20], ansv, ansl;
    bool cmp(P a,P b) {
        if(a.x==b.x) return a.y<b.y;
        return a.x<b.x;
    }
    double length(P a,P b) {
        return sqrt((a-b).dot(a-b));
    }
    double andrew(int n)
    {
        sort(p2,p2+n,cmp);
        int k=0;
        for(int i=0;i<n;i++) {
            while(k>1 && (p3[k-1]-p3[k-2]).det(p2[i]-p3[k-1])<=0)
                k--;
            p3[k++]=p2[i];
        }
        for(int i=n-2,t=k;i>=0;i--) {
            while(k>t && (p3[k-1]-p3[k-2]).det(p2[i]-p3[k-1])<=0)
                k--;
            p3[k++]=p2[i];
        } // 凸包上的点存入p3
    
        double res=0;
        for(int i=1;i<k;i++) // 计算凸包边长 即围栏长度
            res+=length(p3[i],p3[i-1]); 
        return res;
    }
    bool solve(int task)
    {
        int cnt=0, t=task;
        double cntv=0, cntl=0;
        for(int i=0;i<n;i++) {
            if(task&1) cntv+=v[i], cntl+=l[i]; // 被选中的 计算价值及长度
            else p2[cnt++]=p1[i]; // 为被选中的存入p2 待求凸包
            task >>= 1;
        }
        if(cntv>ansv) return 0; // 价值大于已有答案价值 返回0
        double tblen=andrew(cnt); // 求凸包边长 即围栏所需长度
        if(tblen>cntl) return 0; // 若长度不足于围成围栏 返回0
    
        if(cntv==ansv) ansl=min(ansl,cntl-tblen); // 更新余下长度的答案
        else ansv=cntv, ansl=cntl-tblen; // 存在更小的价值 更新价值和长度
        return 1; // 更新了答案 返回1 记录新的状态
    }
    
    int main()
    {
        int c=0;
        while(~scanf("%d",&n)) {
            if(n==0) break; c++;
            for(int i=0;i<n;i++) {
                scanf("%lf%lf",&p1[i].x,&p1[i].y);
                scanf("%lf%lf",&v[i],&l[i]);
            }
    
            int ans;
            ansv=ansl=INF;
            int N=(1<<n)-1;
            for(int i=1;i<N;i++) // 枚举所有状态
                if(solve(i)) ans=i;
    
            printf("Forest %d
    ",c);
            printf("Cut these trees:");
            for(int i=0;i<n;i++) {
                if(ans & 1) printf(" %d",i+1);
                ans >>= 1;
            }
            printf("
    Extra wood: %.2f
    
    ",ansl);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    Asp.Net高级知识回顾_HttpModule及应用程序生命周期_1
    分析Http 请求
    Asp.Net基础知识回顾_状态管理
    泛型约束
    【转】TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端
    【转】【完全开源】微信客户端.NET版
    【转】【完全开源】百度地图Web service API C#.NET版,带地图显示控件、导航控件、POI查找控件
    【转】Android总结篇系列:Activity Intent Flags及Task相关属性
    【转】Android总结篇系列:Activity启动模式(lauchMode)
    【转】Android总结篇系列:Activity生命周期
  • 原文地址:https://www.cnblogs.com/zquzjx/p/9649396.html
Copyright © 2011-2022 走看看