题目
描述
有9个时钟,排成一个3*3的矩阵。
|-------| |-------| |-------|
| | | | | | |
|---O | |---O | | O |
| | | | | |
|-------| |-------| |-------|
A B C
|-------| |-------| |-------|
| | | | | |
| O | | O | | O |
| | | | | | | | |
|-------| |-------| |-------|
D E F
|-------| |-------| |-------|
| | | | | |
| O | | O---| | O |
| | | | | | | |
|-------| |-------| |-------|
G H I
(图 1)
现在需要用最少的移动,将9个时钟的指针都拨到12点的位置。共允许有9种不同的移动。如下表所示,每个移动会将若干个时钟的指针沿顺时针方向拨动90度。
移动 影响的时钟
1 ABDE
2 ABC
3 BCEF
4 ADG
5 BDEFH
6 CFI
7 DEGH
8 GHI
9 EFHI
输入
9个整数,表示各时钟指针的起始位置,相邻两个整数之间用单个空格隔开。其中,0=12点、1=3点、2=6点、3=9点。
输出
输出一个最短的移动序列,使得9个时钟的指针都指向12点。按照移动的序号从小到大输出结果。相邻两个整数之间用单个空格隔开。
样例输入
3 3 0
2 2 2
2 1 2
样例输出
4 5 8 9
解题思路
这道题是熄灯问题的变种,解决熄灯问题的思路同样可以放到这道题上。
灯的状态有四种,对应数字即0123,其中0就是我们想要的状态(指向12点)。也就是说,无论你对一个钟拨多少次,它都只会展现四种状态,也就是 (初始状态+拨钟次数)%4。
除此之外,拨钟的顺序也是不影响最终的结果的。你先拨A钟再拨B钟与先B再A在结果上也没有任何的区别。
不过它与熄灯问题所不同的是,熄灯问题的状态确定方式非常明显,第一行的灯在按过之后会确定下一行灯的状态从而确定对下一行灯进行的操作;而本题的状态之确定却需要仔细地观察题目条件。
在移动的九种操作中,能影响到A钟的操作只有1、2和4,能影响到B钟的操作只有1、2、3和5,而能影响到C钟的是2、3和6。也就是说,如果我们用枚举遍历所有123操作的可能次数的话,剩下的就只有4、5、6操作能够分别单独影响ABC钟。这样我们就能根据执行完123操作后的ABC钟的状态来决定456操作的次数。
同理,456操作的次数确定之后我们就能根据操作完后D和F钟的情况来确定7和9操作的次数了。在1-7、9的操作次数确定以后,我们只需要判断E是否为0加上GHI钟的状态是否相等就可以决定本次所枚举的情况行不行啦。当然题目要求的是最短操作(并不要求顺序),所以还得记得在每次遍历中记录操作再比较长短。
代码
说明:代码语言为C++,其中操作使用一个数组来记录。数组的0-8下标分别对应着1-9操作的次数。代码写的比较简单无脑而且杂乱无章,不喜勿喷~
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
int i = 0;
int j = 0;
int minArr[9] = {
0};
int minSum = 99999;
int myClock[9] = {
0};
int opr[9] = {
0};
int tempClock[9];
for(i = 0; i < 9; i++) {
cin >> myClock[i];
tempClock