zoukankan      html  css  js  c++  java
  • [dfs][凸包]SSL 1703 森林

    传送们

    Description

      森林里面有n棵贵重的树,你需要将它们保护起来。保护树木的方法是给它们做一个围栏(专业术语叫“凸包”),但围栏本身需要用这些树来做,因此需要砍下一些树。砍掉哪些树才能让损失的价值最小呢?如果有个解,取被砍掉的树的数目最小的一组。你可以认为在这样的限制下解是唯一的。

    题解

    其实这题仔细读读题就知道要用dfs做
    那我们怎么实现呢?
    
    dfs的算法其实就是每种情况都搜一遍
    那么,这题有两个方向去拓展
        ①砍树(累计长度)
        ②不砍树(记录,最后判断时求凸包长度)
    那么对于第一种,我们直接累计下木材长度
    第二种,则是创一个新数组,然后将其位置记录下来,累计价值
    那么如果搜完了一次后,判断该木材是否够用(jarvis算法),而且价值是否比之前搜到的状态大
        Tips:一个小小的剪枝,记录下前缀和,如果当前的价值加上后面所有树的价值,还是没有max大,就退出
    
    #include<algorithm>
    #include<stdio.h>
    #include<cmath>
    #define PI 3.1415926535
    using namespace std;
    struct pos
    {
        int x,y,h,v;
        bool operator<(pos a)
        {
            return a.x<x||a.x==x&&a.y<y;
        }
    };
    pos t[16],w[16];
    int sum[16],n,maxV=0;
    bool ans[16],f[16];
    double len=0.0;
    double cj(pos a,pos b,pos c){return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);}
    double dist(pos a,pos b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    double jarvis(int cnt)
    {
        w[0]=(pos){0x7fffffff,0x7fffffff};
        int mark=0;
        for (int i=1;i<=cnt;i++) if (w[i].x<w[mark].x||w[i].x==w[mark].x&&w[i].y<w[mark].y) mark=i;
        double p,C=0;
        int k=mark;
        do
        {
            int i=0;
            double dis=0;
            for (int j=1;j<=cnt;j++)
                if (j!=k)
                {
                    if (i) p=cj(w[k],w[i],w[j]);
                    if (p<0||!i) dis=dist(w[k],w[j]),i=j;
                }
            C+=dis;
            k=i;
        }while(mark!=k);
        if (cnt==1) C=0;
        return C;
    }
    void dfs(int dep,int h,int cnt,int v)
    {
        if (v+sum[n]-sum[dep-1]<maxV) return;
        if (dep==n+1)
        {
            double C=jarvis(cnt-1);
            if (h>=C&&v>maxV)
            {
                maxV=v;
                len=h-C;
                for (int i=1;i<=n;i++) ans[i]=f[i];
            }
            return;
        }
        w[cnt]=t[dep];
        f[dep]=false;
        dfs(dep+1,h,cnt+1,v+t[dep].v);
        w[cnt]=(pos){0,0};
        f[dep]=true;
        dfs(dep+1,h+t[dep].h,cnt,v);
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&t[i].x,&t[i].y,&t[i].v,&t[i].h);
            sum[i]=sum[i-1]+t[i].v;
        }
        dfs(1,0,1,0);
        printf("%.2f
    ",len);
        for (int i=1;i<=n;i++) if (ans[i]) printf("%d ",i);
        printf("
    ");
        return 0;
    }
  • 相关阅读:
    Django(app的概念、ORM介绍及编码错误问题)
    Django(完整的登录示例、render字符串替换和redirect跳转)
    Construct Binary Tree from Preorder and Inorder Traversal
    Single Number II
    Single Number
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
    Binary Tree Zigzag Level Order Traversal
    Recover Binary Search Tree
    Add Binary
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412253.html
Copyright © 2011-2022 走看看