当前位置: 首页 > news >正文

UVa 1016 Silly Sort

题目描述

你的弟弟有一项作业,需要一些帮助。老师给了他一个数字序列,要求按升序排序。在排序过程中,可以交换两个数字的位置。每次交换都有一个成本,即两个数字的和。

你需要编写一个程序,确定排序数字序列的最小成本。

输入格式

输入文件包含多个测试用例。每个测试用例由两行组成:

  • 第一行是一个整数n(n>1)n (n > 1)n(n>1),表示要排序的数字个数
  • 第二行是nnn个不同的正整数(每个数都小于100010001000),表示要排序的数字

输入以一个单独一行的000结束。

输出格式

对于每个测试用例,输出一行,包含测试用例编号和排序该测试用例数字的最小成本。每个测试用例输出后输出一个空行。

样例输入

3 3 2 1 4 8 1 2 4 5 1 8 9 7 6 6 8 4 5 3 2 7 0

样例输出

Case 1: 4 Case 2: 17 Case 3: 41 Case 4: 34

题目分析

这是一个最小成本排序问题,我们需要找到将序列排序所需的最小交换成本。关键在于理解交换操作的本质和如何最小化总成本。

问题本质

将原序列看作一个排列,排序过程就是将这个排列通过交换操作变为恒等排列。每次交换两个数字的成本是它们的和。

关键观察

  1. 循环分解:任何排列都可以分解为若干个不相交的循环。例如:

    • 原序列:3 2 13\ 2\ 1321
    • 排序后:1 2 31\ 2\ 3123
    • 排列为(1→3→1)(1\rightarrow 3\rightarrow 1)(131)一个循环
  2. 循环内交换策略:对于一个长度为kkk的循环,有两种主要的交换策略:

    策略1:仅使用循环内的最小值进行交换

    • 成本 =cycleSum+(k−2)×cycleMin\texttt{cycleSum} + (k-2) \times \texttt{cycleMin}cycleSum+(k2)×cycleMin
    • 解释:用循环内最小值与其他k−1k-1k1个元素各交换一次

    策略2:借助全局最小值进行交换

    • 成本 =cycleSum+cycleMin+(k+1)×globalMin\texttt{cycleSum} + \texttt{cycleMin} + (k+1) \times \texttt{globalMin}cycleSum+cycleMin+(k+1)×globalMin
    • 解释:先将全局最小值引入循环,完成交换后再将其恢复
  3. 策略选择:对于每个循环,我们选择两种策略中成本较小的那个。

算法步骤

  1. 读入数据直到n=0n = 0n=0
  2. 对每个测试用例:
    • 复制原数组并排序,建立位置映射
    • 标记已访问元素
    • 找出所有循环,对每个循环计算两种策略的成本
    • 累加最小成本到总成本
  3. 输出结果

解题思路详解

循环分解的重要性

在排列中,每个元素都有一个"应该去的位置"。当我们跟踪一个元素从当前位置到它应该在的位置,再从那个位置跟踪下一个元素,最终会形成一个循环。

例如样例1:

  • 原序列:3 2 13\ 2\ 1321
  • 排序后:1 2 31\ 2\ 3123
  • 333应该在位置222(从000开始编号),位置222上是111111应该在位置000,位置000上是333,形成一个循环(0→2→0)(0\rightarrow 2\rightarrow 0)(020)

成本计算原理

对于长度为kkk的循环:

策略1的成本推导

  • 需要k−1k-1k1次交换才能让循环内所有元素归位
  • 如果每次都用循环内最小值参与交换,总成本 =(k−1)×cycleMin+(cycleSum−cycleMin)(k-1) \times \texttt{cycleMin} + (\texttt{cycleSum} - \texttt{cycleMin})(k1)×cycleMin+(cycleSumcycleMin)
  • 简化后:cycleSum+(k−2)×cycleMin\texttt{cycleSum} + (k-2) \times \texttt{cycleMin}cycleSum+(k2)×cycleMin

策略2的成本推导

  • 先将全局最小值与循环内最小值交换:成本 =globalMin+cycleMin\texttt{globalMin} + \texttt{cycleMin}globalMin+cycleMin
  • 用全局最小值完成循环内其他k−1k-1k1次交换:成本 =(k−1)×globalMin+(cycleSum−cycleMin)(k-1) \times \texttt{globalMin} + (\texttt{cycleSum} - \texttt{cycleMin})(k1)×globalMin+(cycleSumcycleMin)
  • 最后将全局最小值恢复:成本 =globalMin+cycleMin\texttt{globalMin} + \texttt{cycleMin}globalMin+cycleMin
  • 总成本 =cycleSum+cycleMin+(k+1)×globalMin\texttt{cycleSum} + \texttt{cycleMin} + (k+1) \times \texttt{globalMin}cycleSum+cycleMin+(k+1)×globalMin

为什么策略222可能更优

当循环内最小值远大于全局最小值时,借助全局最小值进行交换可以显著降低成本。特别是当循环较长且循环内元素较大时,策略222的优势更加明显。

复杂度分析

  • 时间复杂度O(nlog⁡n)O(n \log n)O(nlogn),主要来自排序操作
  • 空间复杂度O(n)O(n)O(n),用于存储原数组、排序数组和访问标记

代码实现

// Silly Sort// UVa ID: 1016// Verdict: Accepted// Submission Date: 2025-11-09// UVa Run Time: 0.010s//// 版权所有(C)2025,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;intmain(){intcaseNum=1;intn;while(cin>>n&&n!=0){vector<int>arr(n);for(inti=0;i<n;i++)cin>>arr[i];vector<int>sortedArr=arr;sort(sortedArr.begin(),sortedArr.end());// 位置映射:值 -> 在排序后的索引vector<int>pos(1000,-1);for(inti=0;i<n;i++)pos[sortedArr[i]]=i;vector<bool>visited(n,false);intglobalMin=sortedArr[0];inttotalCost=0;for(inti=0;i<n;i++){if(visited[i]||pos[arr[i]]==i)continue;// 找到一个循环intcycleMin=INT_MAX;intcycleSum=0;intcycleLen=0;intcur=i;while(!visited[cur]){visited[cur]=true;cycleLen++;cycleSum+=arr[cur];if(arr[cur]<cycleMin)cycleMin=arr[cur];cur=pos[arr[cur]];}// 策略1:仅用循环内最小值交换intcost1=cycleSum+(cycleLen-2)*cycleMin;// 策略2:借助全局最小值交换intcost2=cycleSum+cycleMin+(cycleLen+1)*globalMin;totalCost+=min(cost1,cost2);}cout<<"Case "<<caseNum<<": "<<totalCost<<"\n\n";caseNum++;}return0;}

总结

本题的关键在于将排序问题转化为排列的循环分解问题,并通过分析不同交换策略的成本来找到最优解。这种思路在很多排列相关的最优化问题中都有应用,是一个很有用的技巧。

通过循环分解和策略比较,我们能够在O(nlog⁡n)O(n \log n)O(nlogn)的时间复杂度内解决这个问题,对于n≤1000n \leq 1000n1000的数据规模来说是完全可行的。

http://www.jsqmd.com/news/814612/

相关文章:

  • 从DDR3到DDR4,硬件工程师必须知道的5个关键电路变化与避坑指南
  • middleclass测试驱动开发:使用Busted框架编写高质量Lua OOP代码
  • 贵阳购宠避坑指南:5家靠谱实体门店实测推荐 - 速递信息
  • Next.js 全栈应用认证实战:从 Auth.js 核心原理到生产部署
  • 别再只盯着PID了!用Python+Arduino从零搭建一个音圈电机位置控制系统(附完整代码)
  • MPI并行编程避坑指南:矩阵乘法中Send/Recv与Scatter/Bcast的性能差异实测
  • ETS2LA:如何在《欧洲卡车模拟2》中实现智能自动驾驶的终极解决方案
  • 基于微信小程序实现家庭大厨管理系统【项目源码+论文说明】
  • BLDC无感控制入门:从“三段式启动”到稳定运行,手把手调参避坑
  • 基于Markdown的AI助手启动器agent-seed:透明化交互与可进化架构实践
  • 2026 合肥黄金处置|合扬老店当日高价,透明结算无套路 - 奢侈品回收测评
  • 三维集成技术:突破神经形态硬件连接瓶颈的必由之路
  • C# Winform Chart控件避坑指南:从拖控件到实现流畅动态折线图的5个关键步骤
  • 消费电子GNSS技术演进与设计挑战
  • 终极指南:轻松掌握艾尔登法环存档备份与角色迁移技巧
  • 三步解锁WeMod Pro高级功能:免费永久激活完整指南
  • 终极密码恢复指南:ArchivePasswordTestTool帮你快速找回加密压缩包密码
  • 转化率优化全流程解析:从数据驱动到A/B测试实践
  • STALC:多机器人分层协调规划方法解析与应用
  • 免费机票价格监控系统:让AI自动帮你找到最便宜航班
  • fmt异常处理终极指南:如何在无异常环境中安全降级配置
  • 告别Labelme!用Roboflow快速标注你的UNet语义分割数据集(附完整代码)
  • React Unity WebGL最佳实践清单:避免常见错误,构建稳定应用
  • 别再只调ViT了!用CLIP的Zero-Shot能力,5分钟搞定你的自定义图像分类任务
  • 从顺序执行到时间片轮询:裸机多任务架构的轻量化演进
  • Sophia多线程压缩原理:如何自动管理存储空间和垃圾回收
  • Source Han Serif CN:企业级中文排版解决方案深度解析
  • 基于OpenAI API的Discord机器人:从部署到调优的完整指南
  • TCS3490颜色传感器技术解析与应用实践
  • CentOS 7上从源码安装Binwalk踩坑记:解决那个恼人的 ‘No module named pkg_resources‘ 错误