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;
    }
  • 相关阅读:
    d3.js(v5.7)的比例尺以及坐标轴
    d3.js(v5.7)的node与数据匹配(自动匹配扩展函数)
    d3.js(v5.7)的attr()函数完善(添加obj支持)
    d3.js入门之DOM操作
    d3.js入门学习
    最近在写个人网站,忙碌中。。。
    构建vue项目(vue 2.x)时的一些配置问题(持续更新)
    Python之元组
    Python之列表
    Python之字符串
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412253.html
Copyright © 2011-2022 走看看