517-coding #2 贪心算法

本文概述了三种区间相关问题的贪心算法解决方案:1) 最小区间覆盖,通过线段排序和动态维护覆盖边界;2) 选择不相交区间,按右端点递增选择;3) 最少点覆盖所有区间,按右端点优先选取。这些策略适用于大规模数据集,如n=10^5,区间范围10^9。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模型1 : 最小区间覆盖

要总结关于序列贪心的几个模型和相关转化。

给定一个 [1,m] 的区间给出 n 个区间$l_i , r_i $

要求选出最少的区间个数使得 [1,m]整点区间被完全覆盖。

对于100%的数据$1 \leq n \leq 10^5 , 1 \leq l_i,r_i \leq 10^9$

Sol : 对于线段集合按照l排序,而r不管。

    设当前覆盖成功的最右边界是nowr,每次只需要在符合左端点在[1,nowr+1]的线段的右端点取一个max来更新nowr即可。

  具体实现可以用双指针,设当前排除到的线段编号是j,那么之后选取的线段应该是在j之后,复杂度可以到$\Theta (n log_2 n)$

# include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m;
struct rec{ int l,r; }a[N];
bool cmp(rec a,rec b){return a.l<b.l;}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
     scanf("%d%d",&a[i].l,&a[i].r);
    sort(a+1,a+1+n,cmp);
    int nowr=0,ans=0,j=1;
    for (int i=1;i<=n;i++) {
        int mx=0;
        while (j<=n&&a[j].l<=nowr+1) mx=max(mx,a[j].r),j++;
        ans++; nowr=mx;
        if (mx<0) break;
        if (nowr>=m) break;
    }
    if (nowr>=m) printf("%d\n",ans);
    else puts("-1");
    return 0;
}

最小区间覆盖.cpp

  模型2 : 选择不相交区间

  有n个区间$[l_i , r_i] $,最多选取多少的区间,他们之间两两不不相交

  对于100%的数据 $1 \leq n \leq 10^5 , 1 \leq l_i,r_i \leq 10^9$

Sol : 只需要按照右端点$r_i$递增排序,然后按照从前到后遍历每一条线段,能被加入集合的就被加入(即左端点不和之前选的最后一条线段有交)。

  证明:设$r_1 < r_2$ , 证明选择$r_1$比选择$r_2$更优 

    1. 若$l_1 > l_2$   此时区间$[l_2, r_2]$被$[l_1,r_1]$包含,所以如果选择区间$[l_2,r_2]$那么可以为后面留出更大的空间。

      2. 若 $l_1 < l_2$  此时区间$[l_2,r_2]$那么可以为后面留出更大的空间。

  所以上述贪心策略是正确的。

# include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m;
struct rec{ int l,r; }a[N];
bool cmp(rec a,rec b){return a.r<b.r;}
int main()
{
    while (1) {
        scanf("%d",&n); if (n==0) break;
        for (int i=1;i<=n;i++)
         scanf("%d%d",&a[i].l,&a[i].r);
        sort(a+1,a+1+n,cmp);
        int last_r=0,ans=0;
        for (int i=1;i<=n;i++)
            if (a[i].l>=last_r) last_r=a[i].r,ans++;
        printf("%d\n",ans);
    }
    return 0;
}

HDU-2037 (区间端点可以重复)

  模型3 :最少的点覆盖所有的区间 

  有n个区间$[l_i , r_i] $,求最少选取多少个点使得每个区间内都有点。

  对于100%的数据 $1 \leq n \leq 10^5 , 1 \leq l_i,r_i \leq 10^9$

Sol:  按照r排序,每次选的点必然是每条线段的右端点,依次选取。

     由于对于每一条不能被之前点覆盖线段上面任意位置放一个点是对该线段本身无影响,

    而由于以后线段的右端点都在该线段右端点的右侧,所以放在当前最右端可以尽可能覆盖其他线段,

      比其他地方作用效果要么相同,要么更好。

# include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct rec{
    int l,r;
}a[N];
int n;
bool cmp(rec a,rec b){return a.r<b.r;}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
     scanf("%d%d",&a[i].l,&a[i].r);
    sort(a+1,a+1+n,cmp);
    int ans=0,pos=-0x3f3f3f3f;
    for (int i=1;i<=n;i++)
     if (a[i].l<=pos) continue;
     else ans++,pos=a[i].r;
    printf("%d\n",ans);
    return 0;
}

最少点覆盖.cpp

以下为编写代码解决该问题的指示词,按步骤组织: --- ### **代码实现指示** **目标**:开发装箱优化系统,解决食品集团订单包装优化问题 --- #### **1. 数据预处理模块** ```python # 读取附件数据(假设为CSV格式) import pandas as pd # 附件1:包装箱规格(含冷藏/常温标识) df_boxes = pd.read_csv(&#39;附件1.csv&#39;, names=[&#39;Box_ID&#39;, &#39;Length&#39;, &#39;Width&#39;, &#39;Height&#39;, &#39;TL&#39;]) # 附件2:商品尺寸(含是否为冰块) df_items = pd.read_csv(&#39;附件2.csv&#39;, names=[&#39;Item_Code&#39;, &#39;Length&#39;, &#39;Width&#39;, &#39;Height&#39;, &#39;Is_Ice&#39;]) # 附件3:订单数据(含温层TL) df_orders = pd.read_csv(&#39;附件3.csv&#39;, names=[&#39;Order_Code&#39;, &#39;Item_Code&#39;, &#39;Num&#39;, &#39;TL&#39;]) ``` --- #### **2. 体积计算模块** ```python def calculate_total_volume(order): """ 计算订单总需求体积(含冰块) 输入:单个订单数据(需合并商品数量) 输出:总需求体积(cm³) """ total_volume = 0 # 遍历订单中的商品 for item_code, num in zip(order[&#39;Item_Code&#39;], order[&#39;Num&#39;]): item = df_items[df_items[&#39;Item_Code&#39;] == item_code].iloc[0] total_volume += item[&#39;Length&#39;] * item[&#39;Width&#39;] * item[&#39;Height&#39;] * num # 冷藏订单需添加两块冰块 if order[&#39;TL&#39;] == &#39;冷藏&#39;: ice = df_items[df_items[&#39;Is_Ice&#39;] == True].iloc[0] total_volume += ice[&#39;Length&#39;] * ice[&#39;Width&#39;] * ice[&#39;Height&#39;] * 2 return total_volume ``` --- #### **3. 箱子选择算法** ```python def select_optimal_box(total_volume, items, tl): """ 选择最小可用箱子(基于体积和温层) 输入:总需求体积、商品列表、温层 输出:最优箱号、空间利用率、具体摆放方式 """ # 过滤符合温层的箱子并按体积升序排序 candidate_boxes = df_boxes[df_boxes[&#39;TL&#39;] == tl].sort_values(by=&#39;Volume&#39;) # 遍历候选箱子,检查是否能容纳所有物品 for box in candidate_boxes.itertuples(): box_volume = box.Length * box.Width * box.Height if box_volume < total_volume: continue # 三维装箱检查(需实现具体逻辑,此处简化为体积比较) if can_fit_items(box, items): utilization = total_volume / box_volume return box.Box_ID, utilization, generate_layout(box, items) # 若无合适箱子,选择最大6号箱 return 6, total_volume / candidate_boxes.iloc[-1].Volume, "强制使用最大箱" def can_fit_items(box, items): """ 启发式三维装箱检查(示例:贪心算法) 实现建议:使用bin-packing库(如py3dbp)或自定义分层放置逻辑 """ # 示例:按体积降序尝试放置 sorted_items = sorted(items, key=lambda x: x.volume, reverse=True) remaining_space = [box.Length, box.Width, box.Height] for item in sorted_items: # 检查物品能否在当前剩余空间放置 if all(item.dim <= remaining_space for item.dim, remaining_space in zip(item.dimensions, remaining_space)): remaining_space = update_remaining_space(remaining_space, item) else: return False return True ``` --- #### **4. 空间利用率与原包装对比** ```python def compare_optimization(order): """ 对比原包装与优化后结果 输出:节省成本百分比、是否需标记为不合理 """ original_box = order[&#39;Original_Box&#39;] optimized_box = order[&#39;Optimized_Box&#39;] # 获取原箱和新箱的体积 vol_original = df_boxes[df_boxes[&#39;Box_ID&#39;] == original_box].Volume.values[0] vol_optimized = df_boxes[df_boxes[&#39;Box_ID&#39;] == optimized_box].Volume.values[0] cost_saving = (vol_original - vol_optimized) / vol_original * 100 is_unreasonable = optimized_box < original_box # 若优化后箱子更小,则原包装不合理 return cost_saving, is_unreasonable ``` --- #### **5. 主流程** ```python # 遍历所有订单(示例:处理订单1~5) for order in df_orders[df_orders[&#39;Order_Code&#39;].between(1, 5)].itertuples(): # 计算总需求体积 total_vol = calculate_total_volume(order) # 获取商品列表(含尺寸和数量) items = get_items_from_order(order) # 需实现该函数 # 选择最优箱子 optimal_box, utilization, layout = select_optimal_box(total_vol, items, order.TL) # 输出结果 print(f"订单 {order.Order_Code}: 选择箱号 {optimal_box}, 利用率 {utilization:.2%}") ``` --- ### **关键库与工具** 1. **数据处理**:`pandas`、`numpy` 2. **三维装箱算法**:使用现有库(如 `py3dbp`)或自定义启发式算法 3. **可视化**:`matplotlib`(用于绘制装箱示意图) 4. **性能优化**:对大规模订单使用并行计算(`multiprocessing`) --- ### **注意事项** 1. **冷藏订单处理**:务必在总体积中增加冰块体积,且冷藏与常温商品分开装箱。 2. **物理约束**:仅体积足够不代表能实际放入,需验证物品的排列组合。 3. **效率优化**:对订单6~92,可预计算商品组合的常用箱型,减少实时计算量。 通过上述代码框架,可逐步实现问题1~4的求解,最终生成优化结果并填充至附件3表格中。这是上面问题的初步解决代码,请你优化,我的附件是excel文件
03-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值