最优化——贪心策略

Posted 牧空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最优化——贪心策略相关的知识,希望对你有一定的参考价值。

核心思想

  • 总是选择当前情况下最优的策略,能够得到局部最优解。
  • 但对于具备无后效性(即某个状态以前的过程不会影响以后的状态,只与当前状态有关)的问题,贪心策略可以获得全局最优解

例子

简单贪心

一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物
OJ

考虑最少,那么优先考虑兔子;考虑最多,优先考虑鸡

if(a % 2 == 0){
	max = a / 2;
	min = a / 4 + (a % 4) / 2;
}

区间贪心

OJ
两地之间有多个加油站,但每个加油站油价不同,如何以最少的价格到达目的地,或者最远到达哪个位置

  • 加最便宜的油,跑最远的路
  • 只要有更便宜的,就不多跑,刚好到加油站

参考柳神代码

struct Station
{
    double price;
    int distance;
    bool operator<(const Station &b) const
    {
        if (distance == b.distance)
        {
            return price < b.price;
        }
        return distance < b.distance;
    }
};

int main(int argc, char const *argv[])
{
    int cmax, d, davg, n;
    double sum;

    while (scanf("%d %d %d %d", &cmax, &d, &davg, &n) != EOF)
    {
        vector<Station> stations(n + 1);
        stations[n] = {0.0, d};
        for (int i = 0; i < n; i++)
            scanf("%lf %d", &stations[i].price, &stations[i].distance);
        sort(stations.begin(), stations.end());
        double nowDis = 0, maxDis = 0, nowPrice = 0, totalPrice = 0, leftDis = 0;
        if (stations[0].distance != 0)
        {
            printf("The maximum travel distance = 0.00\\n");
            return 0;
        }
        else
        {
            nowPrice = stations[0].price;
        }
        while (nowDis < d)
        {
            maxDis = nowDis + cmax * davg;
            double minPriceDis = 0, minPrice = INT32_MAX;
            int flag = 0;
            for (int i = 1; i <= n && stations[i].distance <= maxDis; i++)
            {
                if (stations[i].distance <= nowDis)
                    continue;
                // 只要有小于当前价格的加油站,就只跑到该加油站,不多跑,之后的路程使用该加油站的价格
                if (stations[i].price < nowPrice)
                {
                    totalPrice += (stations[i].distance - nowDis - leftDis) * nowPrice / davg;
                    leftDis = 0.0;
                    nowPrice = stations[i].price;
                    nowDis = stations[i].distance;
                    flag = 1;
                    break;
                }
                if (stations[i].price < minPrice)
                {
                    minPrice = stations[i].price;
                    minPriceDis = stations[i].distance;
                }
            }
            if (flag == 0 && minPrice != INT32_MAX)
            {
                totalPrice += (nowPrice * (cmax - leftDis / davg));
                leftDis = cmax * davg - (minPriceDis - nowDis);
                nowPrice = minPrice;
                nowDis = minPriceDis;
            }
            if (flag == 0 && minPrice == INT32_MAX)
            {
                nowDis += cmax * davg;
                printf("The maximum travel distance = %.2f\\n", nowDis);
                return 0;
            }
        }

        printf("%.2f\\n", totalPrice);
    }
    return 0;
}

以上是关于最优化——贪心策略的主要内容,如果未能解决你的问题,请参考以下文章

leetcode605. 种花问题贪心策略,局部区间最优解法

leetcode 763. 划分字母区间贪心策略:局部最优大区间划分

《挑战程序设计竞赛》学习笔记

leetcode 435. 无重叠区间贪心策略:优先保留结尾小且不相交的区间,即局部最优连续区间

贪心算法 | 最优装载问题——加勒比海盗船

贪心算法