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

UVa 250 Pattern Matching Prelims

题目分析

本题属于光学字符识别(OCR\texttt{OCR}OCR)中的预处理问题。在字符识别过程中,扫描得到的图像往往存在噪声、形变,导致字符的大小、位置和方向发生变化。为了能够将扫描图像与标准模板进行匹配,需要找到图像中的一个基准点——重心Center of Gravity\texttt{Center of Gravity}Center of Gravity),作为对齐的参考点。

重心的定义

对于一个n×mn \times mn×m的灰度矩阵,每个元素的值在[0,1][0,1][0,1]之间,000表示白色,111表示黑色。重心的位置由行和列分别独立确定:

  • 行的选择:假设重心在第iii行,那么忽略第iii行后,上方所有行的元素之和与下方所有行的元素之和的差值应尽可能小。
  • 列的选择:类似地,忽略第jjj列后,左侧所有列的元素之和与右侧所有列的元素之和的差值应尽可能小。

特别地,如果存在多个满足最小差值的行或列,则选择行号最大、列号最大的那一组。

输入输出格式

  • 输入由多组数据组成,每组数据第一行为两个整数RRRCCC,分别表示矩阵的行数和列数,满足1≤R,C≤251 \leq R, C \leq 251R,C25。接下来是R×CR \times CR×C个浮点数,按照行主序给出。输入以0 0结束。
  • 输出格式:对于每组数据,输出Case k: center at (r, c),其中kkk111开始编号。

样例分析

以题目中的5×55 \times 55×5矩阵为例:

0.7 0.75 0.7 0.75 0.8 0.55 0.3 0.2 0.1 0.7 0.8 0.1 0.0 0.0 0.8 0.7 0.0 0.0 0.0 0.8 0.8 0.9 0.8 0.75 0.9

计算各行元素之和:

  • 111行:3.73.73.7
  • 222行:1.851.851.85
  • 333行:1.71.71.7
  • 444行:1.51.51.5
  • 555行:4.154.154.15

总行和:12.912.912.9

对于行i=3i=3i=3(忽略第333行),上方行和 =3.7+1.85=5.553.7 + 1.85 = 5.553.7+1.85=5.55,下方行和 =1.5+4.15=5.651.5 + 4.15 = 5.651.5+4.15=5.65,差值为0.10.10.1。因此重心在第333行。

类似地,计算各列之和,可得重心在第333列。

解题思路

初步思考

最直接的方法是:对于每一行iii,分别计算上方元素和与下方元素和,然后求差值,找到最小差值对应的行。列也类似。时间复杂度为O(R×C×(R+C))O(R \times C \times (R + C))O(R×C×(R+C))。由于R,C≤25R, C \leq 25R,C25,这个复杂度完全可行(约25×25×50=3125025 \times 25 \times 50 = 3125025×25×50=31250次操作)。

但我们可以进一步优化。

前缀和优化

注意到“忽略第iii行”后,上方元素和就是第111行到第i−1i-1i1行的元素之和,下方元素和就是第i+1i+1i+1行到第RRR行的元素之和。因此,如果我们预先计算出每一行的元素和(即行前缀和),就可以在O(1)O(1)O(1)时间内得到任意分割的上下方元素和。

设:

  • rowSum[i]rowSum[i]rowSum[i]表示原矩阵第iii行的元素之和(1≤i≤R1 \leq i \leq R1iR)。
  • prefixRow[i]=∑k=1irowSum[k]prefixRow[i] = \sum_{k=1}^{i} rowSum[k]prefixRow[i]=k=1irowSum[k]表示前iii行的元素和。

那么:

  • 忽略第iii行后,上方元素和 =prefixRow[i−1]prefixRow[i-1]prefixRow[i1]
  • 下方元素和 =totalSum−prefixRow[i]totalSum - prefixRow[i]totalSumprefixRow[i],其中totalSum=prefixRow[R]totalSum = prefixRow[R]totalSum=prefixRow[R]

差值 =∣prefixRow[i−1]−(totalSum−prefixRow[i])∣=∣totalSum−prefixRow[i]−prefixRow[i−1]∣\big| prefixRow[i-1] - (totalSum - prefixRow[i]) \big| = \big| totalSum - prefixRow[i] - prefixRow[i-1] \big|prefixRow[i1](totalSumprefixRow[i])=totalSumprefixRow[i]prefixRow[i1]

同理,对于列:

  • colSum[j]colSum[j]colSum[j]表示原矩阵第jjj列的元素之和。
  • prefixCol[j]=∑k=1jcolSum[k]prefixCol[j] = \sum_{k=1}^{j} colSum[k]prefixCol[j]=k=1jcolSum[k]
  • 忽略第jjj列后,左侧元素和 =prefixCol[j−1]prefixCol[j-1]prefixCol[j1],右侧元素和 =totalSum−prefixCol[j]totalSum - prefixCol[j]totalSumprefixCol[j]
  • 差值 =∣totalSum−prefixCol[j]−prefixCol[j−1]∣\big| totalSum - prefixCol[j] - prefixCol[j-1] \big|totalSumprefixCol[j]prefixCol[j1]

处理多个最优解

题目要求:如果有多行能使差值最小,选择行号最大的;列同理。因此我们在遍历行和列时,应该从大到小遍历,并仅在遇到更小的差值时才更新答案,这样最后一个遇到的“相等”差值就不会覆盖之前更大的行号。

边界情况

  • R=1R=1R=1时,没有“上方”和“下方”行,此时忽略唯一的一行后,上下方和均为000,差值为000,重心行取111
  • C=1C=1C=1时类似。

在代码实现中,我们从R−2R-2R2开始下降到111,并将初始的最小行设为R−1R-1R1(最后一行的上一行),初始差值设为∣totalSum∣\big|totalSum\big|totalSum。这样可以正确处理边界。

浮点数精度

由于输入是浮点数,直接比较相等可能因精度问题出错。因此我们使用一个小的容差值EPSILON = 1E-6,在比较temp<minDifferencetemp < minDifferencetemp<minDifference时,使用temp + EPSILON < minDifference来避免浮点误差。

代码实现

// Pattern Matching Prelims// UVa ID: 250// Verdict: Accepted// Submission Date: 2016-05-23// UVa Run Time: 0.040s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;constdoubleEPSILON=1E-6;// 浮点数比较的容差值intmain(){cin.tie(0);// 加速输入输出cout.sync_with_stdio(false);vector<double>sumOfRows,sumOfColumns;// 存储行和列的前缀和introw,column,cases=0;while(cin>>row>>column,row&&column)// 读取矩阵大小,遇到0 0结束{sumOfRows.clear();sumOfColumns.clear();sumOfRows.resize(row);// 调整行前缀和数组大小sumOfColumns.resize(column);// 调整列前缀和数组大小fill(sumOfRows.begin(),sumOfRows.end(),0.0);fill(sumOfColumns.begin(),sumOfColumns.end(),0.0);doublevalue;// 读取矩阵元素,同时累加每一行和每一列的和for(inti=0;i<row;i++)for(intj=0;j<column;j++){cin>>value;sumOfRows[i]+=value;// 累加到对应行sumOfColumns[j]+=value;// 累加到对应列}// 计算行前缀和:sumOfRows[i] 现在表示前 i+1 行的元素和for(inti=1;i<sumOfRows.size();i++)sumOfRows[i]+=sumOfRows[i-1];// 计算列前缀和:sumOfColumns[j] 现在表示前 j+1 列的元素和for(intj=1;j<sumOfColumns.size();j++)sumOfColumns[j]+=sumOfColumns[j-1];doubletotal=sumOfRows[row-1];// 矩阵所有元素的总和// 寻找最优行:从最后一行向前遍历,保证遇到相等差值时保留更大的行号intminRow=row-1;doubleminDifference=fabs(total);// 初始差值:忽略第一行时的情况// i 从 row-2 到 1,对应实际行号从 row-1 到 2(因为需要上下都有行)for(inti=row-2;i>=1;i--){// 忽略第 i+1 行(0-indexed)时的差值doubletemp=fabs(total-sumOfRows[i]-sumOfRows[i-1]);// 如果找到更小的差值,更新答案if(temp+EPSILON<minDifference){minRow=i;minDifference=temp;}}// 寻找最优列:从最后一列向前遍历intminColumn=column-1;minDifference=fabs(total);// 初始差值:忽略第一列时的情况for(intj=column-2;j>=1;j--){doubletemp=fabs(total-sumOfColumns[j]-sumOfColumns[j-1]);if(temp+EPSILON<minDifference){minColumn=j;minDifference=temp;}}// 将 0-indexed 转换为 1-indexed 输出minRow++;minColumn++;cout<<"Case "<<++cases;cout<<": center at ("<<minRow<<", "<<minColumn<<")"<<endl;}return0;}

复杂度分析

  • 时间复杂度O(R×C)O(R \times C)O(R×C),主要来自输入读取和前缀和计算,遍历行和列各需O(R+C)O(R + C)O(R+C)
  • 空间复杂度O(R+C)O(R + C)O(R+C),用于存储行和列的前缀和。

总结

本题的核心是利用前缀和技巧将原本需要O(R×C)O(R \times C)O(R×C)的区间和查询优化为O(1)O(1)O(1),从而快速计算忽略某行或某列后的上下/左右元素和。同时需要注意浮点精度处理和多个最优解时的选择规则。

http://www.zskr.cn/news/1341643.html

相关文章:

  • 嵌入式测试学习第 16 天:复位电路、电源电路基础原理
  • Python微服务架构:从单体到分布式的演进
  • UVa 253 Cube Painting
  • 5大优势解锁跨平台直播聚合:PureLive如何重塑你的直播观看体验
  • 2026年4月超纯水设备企业推荐,10吨双级高纯水设备/高纯水设备/超纯水设备/软化水设备,超纯水设备采购渠道怎么选择 - 品牌推荐师
  • 2026年山地车定制厂家综合:途锐达凭何成为口碑之选? - 2026年企业推荐榜
  • 轻量级状态事件总线 eventbusx-js 开源使用教程
  • C/C++函数调用的几种方式总结
  • 2026会议复印机租赁标杆名录:公司复印机租赁/办公室打印机租赁/单位复印机租赁/单位打印机租赁/品牌复印机租赁/选择指南 - 优质品牌商家
  • 2026企业网盘选型对比:坚果云领衔,5款主流产品优劣与场景建议
  • Rust分布式系统最佳实践:构建高可用、高性能的后端服务
  • 15. tsconfig.json 配置详解
  • 专业级图片去重神器:彻底告别重复照片的数字困扰
  • 14. 声明文件(Declaration Files)
  • 2025-2026年国内北京国际小学推荐:五校口碑好的评测 课后活动避免兴趣培养不足注意事项 - 品牌推荐
  • 吉他初学者音阶怎么弹?吉他音阶怎么练效果最好? - 雨林谷
  • 边缘AI框架:在边缘设备上运行AI模型
  • 3步打造智能字幕系统:MaxSubtitle插件深度解析
  • 2026年5月新消息:成都PE给水管制造厂的技术革新与市场格局分析 - 2026年企业推荐榜
  • 深入解析Token质押:从核心原理到未来布局
  • 2026年4月米线加盟品牌选哪家:小吃加盟什么好、小吃加盟品类推荐、小吃加盟店什么好、小吃加盟推荐什么品牌、小吃店加盟联系方式选择指南 - 优质品牌商家
  • 2026年Q2南充广安区域租赁服务商排行及联系方式:四川鼎全机械租赁有限公司联系电话、南充吊车租赁电话、南充施工垫路铁板租赁选择指南 - 优质品牌商家
  • 【蒙古文语音合成行业突破】:ElevenLabs独家支持U+1800–U+18AF+U+18B0–U+18F5双Unicode区段,附官方未公开的蒙古文预处理脚本
  • 【限时解密】ElevenLabs未开放的客家话语音fine-tuning沙箱环境:如何用不到200条标注语句,在72小时内将模型MOS分从3.1提升至4.4(附私有化微调checklist)
  • 毕业设计 深度学习车道线检测(源码+论文)
  • 手写一个AI代码审查员:Claude Agent SDK + MCP 深度实战
  • cursor-vip:当AI编程工具遇上共享经济,你的代码从此有了智能伙伴
  • 雷达信号体制识别
  • 2025-2026年国内新中式实木全屋定制推荐:五大品牌排行评测解决客厅显暗致压抑 - 品牌推荐
  • 2026年4月央国企培训推荐,助你提升职场竞争力,央国企一站式就业服务/应届生央国企上岸培训,央国企培训公司联系电话 - 品牌推荐师