最优化——贪心策略

核心思想

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

例子

简单贪心

一个笼子里面关了鸡和兔子(鸡有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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值