// 此博文为迁移而来,写于2015年3月17日,不代表本人现在的观点与看法。原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vu75.html
嗯。。。。好久没有发考试总结了。今天没事做来水一发。这次考试主题是搜索。。。所以分数大家都挺高的。但是充满魔性的第四题表示还是不太懂正解怎么打。
-------------------------------------------------------------------------------------------------------
1、数字矩阵(number)
问题描述
还别说ZZD平常毛毛躁躁的,考场上的他可毫不含糊,孤身闯阵,奋勇杀敌,多般神勇,一鼓作气地攻下了第一题,第二题,第三题,真可谓一夫当关,万夫莫开啊!当下正浩浩荡荡地朝第四题前进呢。但是,敌人也不是吃干饭的,经受了一二三题的失败后,他们摸清了一个事实,那就是ZZD率领的银河站队所摆的战阵------银河九宫阵(指横、竖和对角线上的战士战斗力之和都等于15的九宫格,每个格子中的数都在1~9之间,并且不重复)非常厉害,所以在第三题之后他们就对这种战阵进行了超强的光子干扰,也就是使阵中每个战士的战斗资料相互间打乱,这样就让战阵的战斗力大打折扣。难怪刚才刷第四题的时候特别困难,ZZD恍然大悟。而他只会领兵作战,至于修复资料的工作自然就叫给了变成天才的你来解决。所以你只需告诉ZZD资料最少移动的步数(指战斗值上下或左右相交换),如果怎么移动都无法恢复战阵,则输出-1。
输入文件(number.in)
一共有50个战阵给你修复;
每个战阵用一个3*3的数字矩阵表示,每一个数表示一个战士的战斗值;
相邻两个数字距阵不用空行隔开。
输出文件(number.out)
应该有50行,每行对应一个距阵修复的最少步数,如无法修复,则为-1。
输入样例
1 5 2
6 9 3
8 4 7
1 8 6
4 2 3
9 5 7
5 1 9
4 8 3
2 7 6
输出样例
5
6
6
样例说明
样例就只给出3个供大家参考啦!
----------------------------------------------------------------------------------------
题解:BFS+hash+Cantor展开。这道题是搜索题,但是不是直接暴搜就搜得到的。不难看出,这道题如果不在BFS的过程中用哈希判重,那么将会爆栈。但是,我们总不可能用九维数组来存hash吧?在哈希判重时,它需要用到康拓展开。康拓展开为什么能够在这里使用?因为对于栈内每一个矩阵,都有且仅有1-9这9个数字且不重复,所以康拓展开式和矩阵一一对应,可以很方便的判重了。
代码:
http://www.cnblogs.com/jinkun113/p/4677226.html
-------------------------------------------------------------------------------------------------------
2、聪明的打字员(clever)
问题描述
阿兰是某机密部门的打字员,她现在接到一个任务:需要在一天之内输入几百个长度固定为6的密码。当然,她希望输入的过程中敲击键盘的总次数越少越好。
不幸的是,出于保密的需要,该部门用于输入密码的键盘是特殊设计的,键盘上没有数字键,而只有以下六个键:Swap0, Swap1, Up, Down, Left, Right,为了说明这6个键的作用,我们先定义录入区的6个位置的编号,从左至右依次为1,2,3,4,5,6。下面列出每个键的作用:
Swap0:按Swap0,光标位置不变,将光标所在位置的数字与录入区的1号位置的数字(左起第一个数字)交换。如果光标已经处在录入区的1号位置,则按Swap0键之后,录入区的数字不变;
Swap1:按Swap1,光标位置不变,将光标所在位置的数字与录入区的6号位置的数字(左起第六个数字)交换。如果光标已经处在录入区的6号位置,则按Swap1键之后,录入区的数字不变;
Up:按Up,光标位置不变,将光标所在位置的数字加1(除非该数字是9)。例如,如果光标所在位置的数字为2,按Up之后,该处的数字变为3;如果该处数字为9,则按Up之后,数字不变,光标位置也不变;
Down:按Down,光标位置不变,将光标所在位置的数字减1(除非该数字是0),如果该处数字为0,则按Down之后,数字不变,光标位置也不变;
Left:按Left,光标左移一个位置,如果光标已经在录入区的1号位置(左起第一个位置)上,则光标不动;
Right:按Right,光标右移一个位置,如果光标已经在录入区的6号位置(左起第六个位置)上,则光标不动。
当然,为了使这样的键盘发挥作用,每次录入密码之前,录入区总会随机出现一个长度为6的初始密码,而且光标固定出现在1号位置上。当巧妙地使用上述六个特殊键之后,可以得到目标密码,这时光标允许停在任何一个位置。
现在,阿兰需要你的帮助,编写一个程序,求出录入一个密码需要的最少的击键次数。
输入文件(clever.in)
文件仅一行,含有两个长度为6的数,前者为初始密码,后者为目标密码,两个密码之间用一个空格隔开。
输出文件(clever.out)
文件仅一行,含有一个正整数,为最少需要的击键次数。
输入样例
123456 654321
输出样例
11
样例说明
初始密码是123456,光标停在数字1上。对应上述最少击键次数的击键序列为:
击键序列: 击键后的录入区
(下划线表示光标所在位置)
123456
Swap1 623451
Right 623451
Swap0 263451
Down 253451
Right 253451
Up 254451
Right 254451
Down 254351
Right 254351
Up 254361
Swap0 654321
最少的击键次数为11。
-------------------------------------------------------------------------------------------------------
题解:BFS+hash,用六种操作方式进行转移。哈希判重的话直接判就是了。
代码:这么水的题就不搞上来啦(PS:其实这道题写的有点丑 = =)
-------------------------------------------------------------------------------------------------------
3、生日快乐(cake)
问题描述
windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕。现在包括windy,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋糕。windy主刀,每一切只能平行于一块蛋糕的一边(任意一边),并且必须把这块蛋糕切成两块。这样,要切成 N 块蛋糕,windy必须切 N-1 次。为了使得每块蛋糕看起来漂亮,我们要求 N 块蛋糕的长边与短边的比值的最大值最小。你能帮助windy求出这个比值么?
输入格式
输入文件cake.in包含三个整数,X Y N。
输出格式
输出文件cake.out包含一个浮点数,保留6位小数。
输入样例
5 5 5
输出样例
1.800000
数据规模和约定
100%的数据,满足 1 <= X,Y <= 10000 ; 1 <= N <= 10 。
-------------------------------------------------------------------------------------------------------
题解:DFS。我能说这题目一道比一道水么 = =!唯一要注意的就是要用双精度浮点数,开始就被坑了。
代码:
#include <cstdio>
#define INF 1<<30
double max(double a,double b)
{
return (a>b)?a:b;
}
double min(double a,double b)
{
return (a<b)?a:b;
}
double DFS(double x,double y,int n)
{
if (n==1) return max(x/y,y/x);
double ans=INF;
for (int i=1;i<=n/2;i++)
{
double tx=x*i/n,ty=y*i/n;
ans=min(ans,max(DFS(tx,y,i),DFS(x-tx,y,n-i)));
ans=min(ans,max(DFS(x,ty,i),DFS(x,y-ty,n-i)));
}
return ans;
}
int x,y,n;
int main()
{
freopen("cake.in","r",stdin);
freopen("cake.out","w",stdout);
scanf("%d%d%d",&x,&y,&n);
printf("%.6f\n",DFS(x,y,n));
return 0;
}
-------------------------------------------------------------------------------------------------------
4、皇宫VS迷宫(palamaze)
问题描述
FISH社会还是封建制度,皇帝是最高统治者,皇宫作为皇帝吃喝完乐的场所,警卫森严,一般人一旦进入,就很难活着出来。与其说它是个皇宫,还不如说他是个迷宫。
这个巨大的迷宫花费了无数蠢得要死的FISH的辛勤劳动建成,因此结构极其复杂,而且到处机关重重。
首先它是由N*M个格子构成的矩形区域。有的格子是石头,无法穿越(黄色部分);而有的格子是水(白色部分),水中如果没有管道(彩色长条),则FISH可以在里面自由泳;但在一些水中可能存在连接上下或左右两个格子的管道,FISH不能逗留在有管道的格子里,但是可以从一个纵向的管道的下面那个格子、穿过这个管道、游到管道上面的那个格子,前提是这两个格子都不是石头。同样也可以反过来游,横向的管道也是类似的。任何管道所在格子都不相邻。
某些格子中还存放有一些管道的钥匙,一旦得到某片钥匙时,就可以改变与之对应的管道(图中颜色相等)的方向,前提是先游到管道所在格的相邻格子(上下左右共边的格子为相邻格)。一旦FISH游到一个格子,FISH就会用最快速度搜寻一遍这个格子和上下左右相邻的格子,然后把在格中找到的钥匙当作宝贝一样的吞进肚子里(要用的时候再吐出来)。一个格子中可能没有钥匙,但不可能有多片钥匙。迷宫中仅存在一个出口,FISH到那一格就可以重见天日。
如果有钥匙,旋转管道是十分快捷的,四肢发达的FISH(虽然似乎没有四肢)将不费吹灰之力迅速的改变某个管道的方向,前提是获得了那个管道的对应钥匙。每一个时刻FISH可以从一个格子游到上下左右相邻的另一个格子(前提:不能游到石头里,也不能有管道),或者穿过某个相邻格的管道达到一个距离为2的格子(上上、下下、左左、右右4个格子),当然也不能为石头或管道。
为了防止其他进入迷宫的人探索出迷宫的出路,迷宫有一种高级自动关闭系统,当它检测到一条FISH进入到迷宫中时,迷宫会自动从0开始计时。当计到10000后,迷宫会自动关闭,里面的一切生灵(包括FISH算了)都无逃逸的可能了——所以一旦进入迷宫,必须在最少的步数内逃离!否则,嘿嘿~ 死得你一瞧起。
虽然很多人对FISH的死将无动于衷,更有甚者将会幸灾乐祸,但是作为一个正直、智慧、无私、伟大、光明、圣洁的人,你觉得应该为FISH做点什么,比如告诉他:至少需要多少时刻才能逃离迷宫(FISH不要高兴的太早,反正告诉了步数你也不一定能够逃出来的)。
输入文件(palamaze.in)
第一行两个数n,m。(n,m<=20)表示n行m列
接下来。N行m列的矩阵。
‘*’表示障碍
‘+’表示正常的路
‘#’表示起点
‘$’表示终点
数字表示钥匙,大写字母表示桥横放,小写字母表示桥竖放
不超过9对字母
其中1对应a,A依次类推
输出文件(palamaze.out)
一行,表示最小步数。如果不能逃出,输出10001。
样例输入
4 4
****
*#+*
*+$*
****
样例输出
2
-------------------------------------------------------------------------------------------------------
题解:这道题还是用来养眼算了。暴力搜索(不论是A*还是BFS)能得40分的样子。正解再说吧。。
代码:。。。
-------------------------------------------------------------------------------------------------------