外星人的房子(2015年4月第六届蓝桥杯)

题目具体信息忘了,不过还能记得主要的信息,大致如下:

1.求外星人两个房子相距的最短距离

2..输入三个数w、m、n,分别表示列数、第一个房子、第二个房子

3.房子排列为从房号1开始,排满当前行后,从下一行的当前列开始,依次填充行中未填充的数字,房号依次递增,当输入w=-6,m=8,n=2时,显示图像部分如下:

图1

4.输出m、n间的最短距离,样例输出为4.

题目分析:

(一)第一种思路

依次计算所有的数据,并填入二维数组,然后按行、列遍历之,求出m、n的距离。

优点:不用寻找图形规律,可暴力破解。

缺点:花费的时间较多,当w、m、n较多时,无法AC。

(二)第二种思路

通过图中显示数据,可以发现数据以为2倍的w为循环显示,那么就可以将数据按照两行划分,依次计算两行,接下来可能有人想到还是遍历数组,那就是又回到第一种思路了。接下来大家看看前两行的数据。

图2

在这里我们假设从左向右为正序,将正序定义为偶数行,逆序定义为奇数行,同时定义i表示当前行,那么在图2中对应的第一行就是第i = 0行,第二行就是第 i = 1行。

那么可以发现偶数行的数据evenData是0 < (i * w) < evenData <= ((i + 1) * w),奇数行的数据oddData是 evenData < oddData <= (i + 1) * w。那么我们怎么把这两行数据表示出来呢?这就是第二种思路的关键了。

大家有没有发现,没两个房子间的距离,最短的走法只有两种,一种先行后列,一种先列后行。不论选取那种方式,都要求走到同行(列)后立即转向,否则就不是所求的最短路径。

解题关键来了,仔细观察图像后就会发现,两个房子间的最短距离是不是可以用行列下标进行运行得到?OK,正解。

那么问题是我们怎么将某个房子号转换为行列下标呢?这就要用到数据结构中的一维数组表示二维数组思想了。

既然我们将数据划分为两行每个模块,那么在进行转换时,就需要按照两行进行转换。

首先,转换行标。行标是最简单的直接除,可以得到式子①,其中的m表示房子序号:

row = m / w ;//①

然后,转换列标。这个就有点技巧了,因为偶数行和奇数行的列标转换是不一样的,偶数行data对2w取余之后,结果都是0<data<=w ,并且列序是正序,那么就可以表示为m % (2 * w) ,其中的;奇数行的data对2w取余后,结果都是(w<data<=2w),这里就要注意列序的相减了,因为是逆序,每行有w个值,那么结果就是(w - m  %  w)。解决了?还没完呢,因为要知道m最小值为1,而我们要的下标是从0开始的,所以最后还要再减去一,整理之后就可以的出下面的式子②:

col = (m % (2 * w) > w ) ? (w - m  %  w) : m % (2 * w) - 1 ;//②

最后,我们就要计算n、m的距离了:

dec = abs(n_row - m_row) + abs(n_col - m_col);

其中的n_row、m_row、n_col、m_col可以套用公式①②求得。

到此,程序结束。

最后附上自己写的代码。

如果分析的有什么错误的地方希望各位看官指正,同时也希望有其他更好的解法:-D。

 1 #include <iostream>
 2 #include <iomanip>
 3 #include <math.h>
 4 using namespace std;
 5
 6 int main(){
 7     int w , m , n ;
 8     cin >> w >> m >> n ;
 9     int m_i = m / w ;
10     int m_j = (m % (2 * w) > w ) ? (w - m % w) : m % (2 * w) ;
11     int n_i = n / w ;
12     int n_j = (n % (2 * w) > w ) ? (w - n % w ) : n % (2 * w)  ;
13     cout << m_i << "," << m_j << endl ;
14     cout << n_i << "," << n_j << endl ;
15     cout << abs(m_i - n_i) + abs(m_j - n_j) << endl ;
16     int ww = w * w ;
17     int sum = 0 ;
18     for(int i = 0 ; i < ww ; i += 2){
19         for(int j = 0 ; j < w ; j++){
20             cout << setw(5) << sum + j + 1 << " ";
21         }
22         cout << endl ;
23         sum += w ;
24         for(int j = w ; j > 0 ; j--){
25             cout << setw(5) << sum + j << " ";
26         }
27         sum += w ;
28         cout << endl ;
29     }
30     return 0;
31 }

时间: 2024-10-05 23:25:26

外星人的房子(2015年4月第六届蓝桥杯)的相关文章

2015第六届蓝桥杯全国软件大赛省赛(预赛)总结

这是我上大学以来第一次自发的写总结,这也许意味着我对大学的看法和接下来的大学生活都将有所改变吧.首先说说引导我写这篇总结的"人物"吧,RUI,从大一开始便是同学,直到大三成为了舍友.他的成绩一直很好,如果没记错的话,大一专业第一名,大二好像也是第一第二的,总之在班里一直名列前茅,在学习成绩里边,最让我羡慕的就是他的英语了,四级和六级都是一次过,并且,六级考了500多分(具体多少记不清了),呃...除了学习成绩好之外,专业能力更是没的说,在大一就加入了学院里的ACM实验室,编程能力那也是

2015年第六届蓝桥杯C/C++B组省赛题目解析

一.奖券数目 有些人很迷信数字,比如带“4”的数字,认为和“死”谐音,就觉得不吉利.虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求.某抽奖活动的奖券号码是5位数(10000-99999),要求其中不要出现带“4”的号码,主办单位请你计算一下,如果任何两张奖券不重号,最多可发出奖券多少张. 请提交该数字(一个整数),不要写任何多余的内容或说明性文字. 分析:直接枚举10000-99999之间的数字,如果带4,直接排除:不带4的,记录一次,直到枚举完后输出. #include <iostream

2015第六届蓝桥杯竞赛感悟

之前对算法一直是敬畏的,觉得很难去学习,但是通过蓝桥杯竞赛也算是强迫自己认真学习了一个多月的算法,发现算法也是可以学的. 前天竞赛就结束了,一直拖到今天才来写一篇总结,其实这次竞赛收货真的蛮大的,自己以前一直不够重视内功的培养,现在能有这么一个机会来修炼内容还是挺开心的. 感觉这次考试题和前两届去比确实难度有所增加,第九题缓存没有写好,第十题压根就没来的及做...其实第十题下来想想是能做的,只是考前最短路径这种动态规划题做的不多,所以在比赛场上就有点怯了...虽然是很想得一等奖参加决赛的,不过照

2015年第六届蓝桥杯省赛真题(自己已懂的题目)

1.问题描述:奖券数目 有些人很迷信数字,比如带"4"的数字,认为和"死"谐音,就觉得不吉利. 虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求.某抽奖活动的奖券号码是5位数(10000-99999), 要求其中不要出现带"4"的号码,主办单位请你计算一下,如果任何两张奖券不重号,最多可发出奖券多少张. 请提交该数字(一个整数),不要写任何多余的内容或说明性文字. 思路:5重循环,第一重为1-9,其余为0-9(这样就可以遍历10000到9999

2015年第六届蓝桥杯C/C++程序设计本科B组决赛 ——居民集会(编程大题)

标题:居民集会 蓝桥村的居民都生活在一条公路的边上,公路的长度为L,每户家庭的 位置都用这户家庭到公路的起点的距离来计算,第i户家庭距起点的距 离为di.每年,蓝桥村都要举行一次集会.今年,由于村里的人口太多,村委 会决定要在4个地方举行集会,其中3个位于公路中间,1个位最公路 的终点. 已知每户家庭都会向着远离公路起点的方向去参加集会,参加集会的 路程开销为家庭内的人数ti与距离的乘积. 给定每户家庭的位置di和人数ti,请为村委会寻找最好的集会举办地 :p1, p2, p3, p4 (p1<

WINDOWS 10 企业版LTSB 2015年11月补丁更新情况

WINDOWS 10 企业版LTSB 2015年11月补丁与其他WINDOWS 10版本自动更新KB3105213,按微软对LTSB的规划,LTSB不会轻易增加新功能,所以不会收到其他版本推送的1511更新包,安装这个KB3105213不会改变LTSB内部版本号,LTSB目前内部版本号还是10240, 不会更新到10586版本. LTSB的内部版本按以前的官方说明,一年只会升级一次

传智播客_2015年Java基础视频-深入浅出精华版 笔记(2015年9月14日23:11:11)

本笔记是个人笔记+摘录笔记相结合,非完全原创 day01 win 7系统打开DOS有趣方法:按住shift+右键,单击“在此处打开命令窗口”(注意:在此处可以是任何的文件夹,不一定是桌面) 用DOS删除的文件不可以在回收站恢复?!! 常用DOS命令d: 回车 盘符切换dir(directory):列出当前目录下的文件以及文件夹md (make directory) : 创建目录(创建文件夹)rd (remove directory): 删除目录(删除文件夹,注意:前提是文件夹必须是空的!!)如果

2015年8月27日课程作业(文件权限管理及grep正则和扩展正则表达式)-JY1506402-19+liuhui880818

学习内容:文件权限管理及grep正则和扩展正则表达式 系统环境:CentOS 6.7/7 x86_64 一.作业(练习)内容: 1.总结本此课程中所涉及命令的使用方法及相关示例展示: 2.总结基本正则表达式及扩展正则表达式 3.显示/etc/passwd文件中以bash结尾的行 4.显示/etc/passwd文件中的两位数或三位数 5.显示`netstat -tan`命令结果中以'LISTEN'后跟0个.1个或者多个空白字符结尾的行 6.添加用户bash.testbash.basher以及nol

linux运维实战练习-2015年8月30日课程作业(练习)安排

一.作业(练习)内容: 1.总结文本编辑工具vim的使用方法: 2.总结文件查找命令find的使用方法: 3.总结bash环境变量的相关内容: 4.总结Linux文件系统上的特殊权限(SUID.SGID.Sticky)的知识点: 5.总结Linux磁盘管理.文件系统相关知识点及其相关命令的使用方法: 6.复制/etc/grub.cfg配置文件至/tmp目录,用查找替换命令删除/tmp/grub.cfg文件中的行首的空白字符: 7.复制/etc/rc.d/init.d/functions文件至/t