news 2026/4/23 17:34:56

UVa 11370 Moogle

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 11370 Moogle

题目描述

你正在为Maple mPhone\texttt{Maple mPhone}Maple mPhone开发一款名为Moogle Maps\texttt{Moogle Maps}Moogle Maps的地图软件。 该软件需要能够显示像“主街131313号”这样的房屋地址位置。 但由于手机存储容量有限, 你不能存储每个房屋的精确位置, 而是只存储一个子集的位置, 其余房屋的位置通过线性插值得到。 你的目标是选择要存储的房屋位置, 使得所有房屋的平均插值误差最小。 街道被视为一条直线, 并且你必须始终存储第一个和最后一个房屋的位置。

给定你存储了房屋iiijjj的位置xix_ixixjx_jxj, 且它们之间没有存储其他房屋, 则对于房屋编号kkk(满足i<k<ji < k < ji<k<j), 其插值位置为:

xi+(xj−xi)⋅k−ij−i x_i + (x_j - x_i) \cdot \frac{k-i}{j-i}xi+(xjxi)jiki

输入格式

第一行包含一个整数ttt1≤t≤501 \leq t \leq 501t50), 表示测试用例的数量。

每个测试用例包含两行。 第一行包含两个整数hhhccc2≤h≤2002 \leq h \leq 2002h2002≤c≤h2 \leq c \leq h2ch), 其中hhh是街道上的房屋数量,ccc是可以存储的房屋位置数量。 第二行包含hhh个按递增顺序排列的整数, 表示每个房屋的位置, 每个位置在区间[0,1000000][0, 1000000][0,1000000]内。

输出格式

对于每个测试用例, 输出在最优选择ccc个房屋位置存储的情况下, 所有hhh个房屋的平均插值误差。 输出应保留四位小数, 允许±0.001\pm 0.001±0.001的误差。

题目分析

这是一个典型的动态规划问题, 需要在必须选择第一个和最后一个房屋位置的约束下, 从hhh个点中选择ccc个点进行存储, 使得所有点的插值误差(绝对误差)的平均值最小。

核心思路

  1. 误差计算: 如果选择存储房屋iiijjji<ji < ji<j), 且它们之间没有其他存储点, 则对于中间的任何房屋kkki<k<ji < k < ji<k<j), 其插值误差为∣xk−(xi+(xj−xi)⋅k−ij−i)∣\lvert x_k - (x_i + (x_j - x_i) \cdot \frac{k-i}{j-i}) \rvertxk(xi+(xjxi)jiki)∣。 我们可以预先计算任意两点iiijjj作为相邻存储点时, 中间所有房屋的误差和, 记为error[i][j]error[i][j]error[i][j]

  2. 动态规划状态定义: 定义dp[i][k]dp[i][k]dp[i][k]表示以房屋iii作为第kkk个被存储的点时, 前iii个房屋(包括iii)的最小总误差和。 这里“第kkk个”意味着我们总共选择了kkk个存储点, 并且最后一个点正好是iii

  3. 状态转移方程: 要计算dp[i][k]dp[i][k]dp[i][k], 我们需要考虑上一个存储点jjjj<ij < ij<i), 且jjj是第k−1k-1k1个存储点。 那么从jjjiii之间的房屋(不包括jjjiii)的误差就是error[j][i]error[j][i]error[j][i]。 因此, 状态转移方程为:
    dp[i][k]=min⁡0≤j<i{dp[j][k−1]+error[j][i]} dp[i][k] = \min_{0 \leq j < i} \{ dp[j][k-1] + error[j][i] \}dp[i][k]=0j<imin{dp[j][k1]+error[j][i]}

  4. 边界条件: 由于第一个房屋必须被存储, 所以dp[0][1]=0dp[0][1] = 0dp[0][1]=0。 其他状态初始化为一个很大的值(表示不可达或误差无穷大)。

  5. 最终答案: 由于最后一个房屋也必须被存储, 我们需要的是dp[h−1][c]dp[h-1][c]dp[h1][c], 即最后一个房屋是第ccc个存储点时的最小总误差。 平均误差即为dp[h−1][c]/hdp[h-1][c] / hdp[h1][c]/h

算法步骤

  1. 读取输入数据。
  2. 对于每个测试用例:
    • 读取hhh,ccc和房屋位置数组loclocloc
    • 预处理计算errorerrorerror矩阵: 对于所有0≤i<j<h0 \leq i < j < h0i<j<h, 计算error[i][j]error[i][j]error[i][j]
    • 初始化dpdpdp数组为无穷大, 设置dp[0][1]=0dp[0][1] = 0dp[0][1]=0
    • 进行动态规划: 遍历iii000h−1h-1h1kkk111ccc, 对于每个合法的dp[i][k]dp[i][k]dp[i][k], 尝试将其状态转移到所有j>ij > ij>i作为下一个存储点。
    • 计算平均误差dp[h−1][c]/hdp[h-1][c] / hdp[h1][c]/h并输出。
  3. 输出结果保留四位小数。

复杂度分析

  • 时间复杂度: 预处理errorerrorerror矩阵需要O(h3)O(h^3)O(h3), 动态规划需要O(h2c)O(h^2 c)O(h2c)。 由于h≤200h \leq 200h200c≤hc \leq hch, 总计算量在可接受范围内。
  • 空间复杂度: 需要O(h2)O(h^2)O(h2)存储errorerrorerror矩阵和O(h×c)O(h \times c)O(h×c)存储dpdpdp数组。

代码实现

// Moogle// UVa ID: 11370// Verdict: Accepted// Submission Date: 2025-12-20// UVa Run Time: 0.040s//// 版权所有(C)2025,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;doublesolve(){inth,c;cin>>h>>c;vector<double>loc(h);for(inti=0;i<h;i++)cin>>loc[i];// 计算误差矩阵:error[i][j] 表示存储点 i 和 j 之间(不包括 i, j)的误差和vector<vector<double>>error(h,vector<double>(h,0.0));for(inti=0;i<h;i++){for(intj=i+1;j<h;j++){doublesum=0.0;for(intk=i+1;k<j;k++){// 计算房屋 k 的插值位置doubleinterp=loc[i]+(loc[j]-loc[i])*(k-i)/double(j-i);sum+=fabs(interp-loc[k]);// 累加绝对误差}error[i][j]=sum;}}// dp[i][k]: 以房屋 i 作为第 k 个存储点的最小误差和vector<vector<double>>dp(h,vector<double>(c+1,1e30));dp[0][1]=0.0;// 第一个房屋是第一个存储点,误差为0// 动态规划for(inti=0;i<h;i++){for(intk=1;k<=c;k++){if(dp[i][k]>1e29)continue;// 不可达状态// 尝试将 i 作为当前最后一个存储点,选择下一个存储点 jfor(intj=i+1;j<h;j++){if(k+1<=c){dp[j][k+1]=min(dp[j][k+1],dp[i][k]+error[i][j]);}}}}// 最后一个房屋必须是第 c 个存储点returndp[h-1][c]/h;}intmain(){ios::sync_with_stdio(false);cin.tie(nullptr);cout<<fixed<<setprecision(4);intt;cin>>t;while(t--)cout<<solve()<<"\n";return0;}

总结

本题的关键在于将问题转化为一个动态规划模型, 并正确处理必须选择首尾房屋的约束条件。 通过预处理任意两点作为相邻存储点时的误差和, 我们可以高效地进行状态转移。 算法的时间复杂度对于题目给定的数据范围是完全可行的。 注意在实现时, 要使用double类型来存储误差值, 并在输出时控制精度。

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

Linly-Talker支持语音指令唤醒功能

Linly-Talker 的语音唤醒&#xff1a;让数字人真正“听懂”你 在智能家居设备日益复杂的今天&#xff0c;一个微小但关键的体验差异往往决定了用户是觉得“智能”&#xff0c;还是觉得“智障”。想象一下&#xff1a;你双手端着咖啡走进客厅&#xff0c;想问问今天的天气——如…

作者头像 李华
网站建设 2026/4/23 11:26:46

AI博物馆讲解员:7×24小时无休导览服务实现

AI博物馆讲解员&#xff1a;724小时无休导览服务实现 在一座省级博物馆的青铜器展厅里&#xff0c;一位老人站在展柜前&#xff0c;轻声问道&#xff1a;“这尊鼎是哪个朝代的&#xff1f;”话音刚落&#xff0c;屏幕上的虚拟讲解员便微微抬头&#xff0c;嘴角自然上扬&#xf…

作者头像 李华
网站建设 2026/4/23 14:43:49

Linly-Talker对网络带宽的要求及离线使用可能性

Linly-Talker 对网络带宽的要求及离线使用可能性 在虚拟主播、智能客服和数字员工日益普及的今天&#xff0c;一个关键问题逐渐浮现&#xff1a;这些依赖AI驱动的数字人系统&#xff0c;是否必须时刻“在线”&#xff1f;尤其是在工厂内网、偏远地区或对数据安全要求极高的场景…

作者头像 李华
网站建设 2026/4/23 12:10:22

4、Windows Server 2008网络知识全解析

Windows Server 2008网络知识全解析 1. Windows Server 2008网络的可扩展性 大型组织通常有众多用户和大量信息需要管理。Active Directory在设计时就考虑到了可扩展性,它不仅能在单个域中存储数百万个对象,还提供了在服务器和不同位置之间分发必要信息的方法。这些特性减轻…

作者头像 李华
网站建设 2026/4/23 1:03:27

8、网络IP地址与子网掩码的选择及IPv6特性解析

网络IP地址与子网掩码的选择及IPv6特性解析 1. 网络场景与子网掩码选择 在网络管理中,合理选择子网掩码至关重要,它直接影响网络的可扩展性和主机数量。以下是不同网络场景下子网掩码的选择分析: - 场景一:大型IP路由网络扩展 - 原网络使用地址137.25.0.0,由20个子网…

作者头像 李华
网站建设 2026/4/23 14:34:14

13、深入理解 DNS:原理、配置与故障排除

深入理解 DNS:原理、配置与故障排除 1. DNS 概述 DNS(Domain Name System)是一套标准协议,它定义了在数据库中查询和更新地址信息的机制、在服务器间复制数据库信息的机制,以及数据库的架构。其主要目的是将易于记忆的域名转换为计算机可识别的 IP 地址,方便用户访问网…

作者头像 李华