• luogu P1250 种树


    我来总结一下最常用的两种办法

    1.贪心

    2.差分约束

    那么我们先来讲,贪心版《种树》

    大家可能知道有一个题和这个类似,那个是钉钉子而这个是种树

    我们可以借用钉钉子的思路来想,首先这个是让你求最小值,而且每个人都有自己划定的区间,并且他们还要求在这段区间内最少种T棵树。

    那么我们既要满足最少种树数,而且要满足每个人的要求。好在的是,题目中说过区间和区间之间可能会有一段重叠,那么我们要抓住这个机会尽可能多的在每一段重复区间内多种树,所以就会产生一个连锁反应,就是上一个重复区间内种的树可能会满足下一个人的要求,那么这个人就可以略过去,以达到最少数的目的。

    (以下是贪心代码,体会一下)

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 31000;
    int n,m,ans=0;
    bool u[N]={0};
    struct Edge{
        int x,y,z;
    }a[N];
    bool cmp(Edge a,Edge b)
    {
        return a.y<b.y;
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=m;i++)
            cin>>a[i].x>>a[i].y>>a[i].z;
        sort(a+1,a+m+1,cmp);
        for(int i=1;i<=m;i++)
        {
            int sum=0;
            for(int j=a[i].x;j<=a[i].y;j++)
            if(u[j]) sum++;//统计已有的数量
            if(sum>=a[i].z) continue;//满足就继续
            for(int k=a[i].y;k>=a[i].x;k--)//不满足情况
            {
                if(!u[k])
                {
                    u[k]=1;
                    sum++;
                    ans++;//答案++
                    if(sum==a[i].z) break;//直到满足,退出
                }
            }
        }
        cout<<ans;//输出最后答案(即最少的树的数量)
        return 0;
    }

    接下来我们讲,差分约束版《种树》

    我们都知道差分约束是用于最短路不等式问题的

    这里我们利用差分约束解决最短路不等式的性质来看

    我们想在区间内种最少的树,所以根据性质

    我们可以列出两个差分约束公式

    1.sum[x]-sum[y-1]>=c;(这里是指在区间[y,x]中至少种c棵树)

    2.0<=sum[x]-sum[x-1]<=1;(这里是指一个单位长度内最多种1棵树)

    根据公式,我们可以建边,但是建边是y+1->y=-1而不是y->y+1=1

    建好边我们就可以跑一边SPFA啦,最少种树数也就出来了!

    (差分约束代码,体会一下)

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 31000;
    const int M = 110000;
    int n,m;
    int dis[N];
    bool vis[N];
    int head[N],num;
    struct Edge{
        int to,next,w;
    }s[M];
    void add(int u,int v,int w)//根据公式建边
    {
        s[++num].w=w;
        s[num].next=head[u];
        head[u]=num;
        s[num].to=v;
    }
    void spfa(int x)//SPFA经典操(ban)作(zi)
    {
        queue<int> q;
        q.push(x);
        for(int i=0;i<=n+1;i++)
            dis[i]=1;
        dis[x]=0;vis[x]=1;
        while(!q.empty())
        {
            int g=q.front();
            q.pop();
            vis[g]=0;
            for(int i=head[g];i!=-1;i=s[i].next)
            {
                int t=s[i].to;
                if(dis[t]>dis[g]+s[i].w)
                {
                    dis[t]=dis[g]+s[i].w;
                    if(!vis[t])
                    {
                        q.push(t);
                        vis[t]=1;               
                    }
                }
            }
        }
    }
    int main()
    {
        int a,b,c,minn=123456789;
        memset(head,-1,sizeof(head));
        cin>>n>>m;
        int y=n+1;
        for(int i=0;i<=n;i++) add(y,i,0);
        for(int i=1;i<=m;i++)
        {
            cin>>a>>b>>c;
            add(b,a-1,-c);
        }
        for(int i=1;i<=n;i++)//建边操作
        {
            add(i-1,i,1);
            add(i,i-1,0);
        }
        spfa(y);
        for(int i=0;i<=n;i++)//取最小值
            minn=min(minn,dis[i]);
        cout<<dis[n]-minn<<endl;
        return 0;
    }

    烟雨江南,无你何欢!

  • 相关阅读:
    使用Azure进行自动化机器学习
    关于ML.NET v1.0 RC的发布说明
    关于ML.NET v0.8的发布说明
    使用ML.NET + Azure DevOps + Azure Container Instances打造机器学习生产化
    使用ML.NET + ASP.NET Core + Docker + Azure Container Instances部署.NET机器学习模型
    neo4j 数据库迁移
    ubuntu1604 搜狗输入法安装
    Chrome 键盘快捷键
    Ubuntu Cleaner清理工具
    bash 数组
  • 原文地址:https://www.cnblogs.com/xmex/p/10150700.html
Copyright © 2020-2023  润新知