news 2026/8/19 8:18:12

UVa 10053 Envelopes

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 10053 Envelopes

题目大意

你有MMM张贺卡(1≤M≤51 \leq M \leq 51M5)和NNN种信封(M≤N≤10M \leq N \leq 10MN10)可以选择。每张贺卡需要放入一个独立的信封中,贺卡可以任意角度旋转(包括斜着放),只要它能完全装入信封内即可。每种信封有特定的尺寸(长LiL_iLi,宽WiW_iWi)和价格CiC_iCi。你需要为每张贺卡分配一个信封(不能重复使用同一种信封的同一实体),使得总花费最小。如果无法为所有贺卡分配信封,则输出cannot buy;否则输出最小花费对应的信封编号(按输入顺序从111开始编号)。如果有多组解,输出任意一组即可。

题目分析

这道题看似简单,但实际上涉及几何判断和组合优化两个难点:

  1. 几何判断:判断一张尺寸为l×wl \times wl×w的贺卡能否放入一个尺寸为L×WL \times WL×W的信封中。贺卡可以任意旋转(包括斜放),因此不能简单地比较长宽。
  2. 组合优化:在NNN种信封中为MMM张贺卡分配信封,每种信封只能使用一次,要求总花费最小。由于M≤5M \leq 5M5N≤10N \leq 10N10,数据规模很小,可以直接使用回溯搜索。

几何判断部分

对于贺卡尺寸a=max⁡(l,w)a = \max(l,w)a=max(l,w)b=min⁡(l,w)b = \min(l,w)b=min(l,w)和信封尺寸A=max⁡(L,W)A = \max(L,W)A=max(L,W)B=min⁡(L,W)B = \min(L,W)B=min(L,W),贺卡可以放入信封的条件是:存在一个旋转角度θ\thetaθ,使得贺卡在水平和垂直方向上的投影长度同时不超过信封的对应边长。

用公式表示就是:存在θ∈[0,π/2]\theta \in [0, \pi/2]θ[0,π/2]使得
acos⁡θ+bsin⁡θ≤A a \cos\theta + b \sin\theta \leq Aacosθ+bsinθA
asin⁡θ+bcos⁡θ≤B a \sin\theta + b \cos\theta \leq Basinθ+bcosθB
同时成立。

特殊情况

  • a≤Aa \leq AaAb≤Bb \leq BbB时,可以直接对齐放置(θ=0\theta = 0θ=0π/2\pi/2π/2)。
  • b>Bb > Bb>B时,无论怎么旋转,短边投影至少为bbb,因此不可能放入。
  • b≤Bb \leq BbBa>Aa > Aa>A时,需要通过斜放来减小长边方向的投影。

在代码实现中,我们采用数值方法:在[0,π/2][0, \pi/2][0,π/2]区间内以较小步长(如0.0010.0010.001弧度)搜索θ\thetaθ,检查是否存在满足条件的角度。

组合优化部分

由于MMM很小(最多555),我们可以使用回溯法(DFS\texttt{DFS}DFS)枚举所有可能的分配方案。状态表示为当前已分配的贺卡数量idx和当前总花费currentCost。使用一个布尔数组used记录每种信封是否已被使用。

剪枝优化:当currentCost已经大于等于当前找到的最小花费minCost时,直接返回,不再继续搜索。

复杂度分析:最坏情况下需要检查P(N,M)=N!(N−M)!P(N, M) = \frac{N!}{(N-M)!}P(N,M)=(NM)!N!种分配方案,当N=10N=10N=10M=5M=5M=5时,这个值约为302403024030240,加上几何判断的开销,完全在可接受范围内。

解题步骤

  1. 读入数据:注意输入可能包含多个测试用例,以0 0结束。
  2. 预处理:对每张贺卡和每种信封,判断贺卡能否放入信封(考虑斜放)。
  3. 回溯搜索
    • 从第000张贺卡开始,尝试为它分配一个未被使用且能放入的信封。
    • 标记该信封为已使用,更新花费,递归处理下一张贺卡。
    • 回溯时恢复信封的未使用状态。
    • 当所有贺卡都分配完毕时,更新最小花费和最优分配方案。
  4. 输出结果
    • 按照题目格式输出测试用例编号。
    • 如果找到可行方案,输出每个贺卡对应的信封编号(输入顺序从111开始)。
    • 否则输出cannot buy
    • 注意相邻测试用例之间输出一个空行。

代码实现

// Envelopes// UVa ID: 10053// Verdict: Accepted// Submission Date: 2025-12-25// UVa Run Time: 0.000s//// 版权所有(C)2025,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;structCard{intl,w;};structEnvelope{intL,W,cost,id;};intm,n,minCost;vector<Card>cards;vector<Envelope>envelopes;vector<int>bestAssign,currentAssign;vector<bool>used;boolfound;constdoublePI=acos(-1.0);constdoubleEPS=1e-8;// 判断贺卡能否放入信封(考虑斜放)boolcanFit(constCard&card,constEnvelope&env){doublea=max(card.l,card.w);doubleb=min(card.l,card.w);doubleA=max(env.L,env.W);doubleB=min(env.L,env.W);// 检查是否可以直接对齐放(不旋转或旋转90度)if(a<=A+EPS&&b<=B+EPS)returntrue;if(a<=B+EPS&&b<=A+EPS)returntrue;// 旋转90度// 如果短边b > B,且长边a > A,不可能放(因为旋转只会让投影更大)if(b>B+EPS)returnfalse;// 现在 b <= B,但 a > A,需要斜着放// 数值搜索 θ 在 [0, π/2] 之间for(doubletheta=0.0;theta<=PI/2.0;theta+=0.001){doubleproj1=a*cos(theta)+b*sin(theta);doubleproj2=a*sin(theta)+b*cos(theta);if(proj1<=A+EPS&&proj2<=B+EPS)returntrue;if(proj1<=B+EPS&&proj2<=A+EPS)returntrue;// 信封可旋转}returnfalse;}// 回溯搜索voidbacktrack(intidx,intcurrentCost){if(currentCost>=minCost)return;// 剪枝if(idx==m){minCost=currentCost;bestAssign=currentAssign;found=true;return;}for(inti=0;i<n;++i){if(!used[i]&&canFit(cards[idx],envelopes[i])){used[i]=true;currentAssign[idx]=i;backtrack(idx+1,currentCost+envelopes[i].cost);used[i]=false;}}}intmain(){intcaseNum=1;while(cin>>m>>n&&(m||n)){cards.resize(m);for(inti=0;i<m;++i)cin>>cards[i].l>>cards[i].w;envelopes.resize(n);for(inti=0;i<n;++i){cin>>envelopes[i].L>>envelopes[i].W>>envelopes[i].cost;envelopes[i].id=i+1;}found=false;minCost=INT_MAX;currentAssign.resize(m);bestAssign.resize(m);used.assign(n,false);backtrack(0,0);if(caseNum>1)cout<<endl;cout<<"Case #"<<caseNum++<<endl;if(found){for(inti=0;i<m;++i)cout<<envelopes[bestAssign[i]].id<<endl;}else{cout<<"cannot buy"<<endl;}}return0;}

算法要点总结

  1. 几何判断是核心:正确判断贺卡能否斜放入信封是本題的关键。采用数值搜索方法简单可靠。
  2. 回溯搜索可行:由于数据规模小,回溯法足以在时限内找到最优解。
  3. 剪枝优化必要:即使数据小,简单的剪枝也能显著减少搜索空间。
  4. 注意输出格式:测试用例编号、空行、信封编号从111开始等细节。

复杂度分析

  • 几何判断:每次判断最多搜索约157015701570个角度(π/2÷0.001\pi/2 \div 0.001π/2÷0.001),常数较大但可接受。
  • 回溯搜索:最坏情况约302403024030240种分配,每种分配需要MMM次几何判断。
  • 总复杂度约为O(M!⋅N⋅K)O(M! \cdot N \cdot K)O(M!NK),其中KKK是几何判断的常数因子。在实际测试中运行速度很快。

拓展思考

  • 如果MMMNNN更大,可能需要使用状态压缩动态规划(DP\texttt{DP}DP)。
  • 几何判断可以进一步优化,使用解析方法直接计算而不需要数值搜索。
  • 题目中“信封纸张很薄”意味着可以紧密贴合,因此我们的几何模型是合理的。

关键点:理解贺卡可以斜放的条件,并采用合适的数值方法进行判断,再结合回溯搜索找到最小花费的分配方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/16 12:09:37

【大模型自动化革命】:Open-AutoGLM如何重塑企业级AI应用生态?

第一章&#xff1a;大模型自动化革命的起点人工智能正经历一场由大模型驱动的范式转变&#xff0c;这场变革的核心在于“自动化”——不仅是任务的自动执行&#xff0c;更是知识生成、系统优化与决策闭环的自主演进。随着算力基础设施的成熟和预训练技术的突破&#xff0c;大模…

作者头像 李华
网站建设 2026/8/9 10:22:47

彻底清除Open-AutoGLM模型文件(附5个命令行实操步骤+可视化工具推荐)

第一章&#xff1a;下载的Open-AutoGLM模型怎么删除在本地开发或测试过程中&#xff0c;Open-AutoGLM 模型可能被缓存到磁盘中以提升加载效率。当不再需要这些模型文件时&#xff0c;手动清理可释放存储空间并避免版本冲突。确认模型存储路径 默认情况下&#xff0c;Open-AutoG…

作者头像 李华
网站建设 2026/8/7 12:05:15

Open-AutoGLM底层技术全曝光:9大核心模块如何重构AI推理效率

第一章&#xff1a;Open-AutoGLM底层技术全貌Open-AutoGLM 是一个面向自动化自然语言理解与生成任务的开源框架&#xff0c;其核心设计融合了图神经网络&#xff08;GNN&#xff09;、大语言模型&#xff08;LLM&#xff09;推理优化与动态任务调度机制。该系统通过构建语义-结…

作者头像 李华
网站建设 2026/8/1 11:53:44

16、使用 Weave Net 搭建 Docker 容器网络

使用 Weave Net 搭建 Docker 容器网络 1. Weave Net 简介 Weave Net 是一款适用于 Docker 的第三方网络解决方案。早期,它为用户提供了 Docker 原生功能之外的额外网络功能,例如在 Docker 开始支持用户定义的覆盖网络和嵌入式 DNS 之前,Weave 就已经提供了覆盖网络和 Weav…

作者头像 李华
网站建设 2026/8/17 18:21:22

Dify + GPU算力加速:实现高性能AI应用落地

Dify GPU算力加速&#xff1a;实现高性能AI应用落地 在企业争相拥抱大模型的今天&#xff0c;一个现实问题摆在面前&#xff1a;如何让AI从“能用”变成“好用”&#xff0c;又能快速上线、稳定运行&#xff1f;许多团队投入大量人力开发RAG系统或智能客服&#xff0c;结果却卡…

作者头像 李华