您的位置:首页 > 其它

Vijos1016.北京2008的挂钟

2015-08-04 17:37 1096 查看
试题请参见: https://vijos.org/p/1016

题目概述



在2008北京奥运会雄伟的主会场的墙上, 挂着如上图所示的3*3的九个挂钟(一开始指针即时针指向的位置请根据输入数据调整). 然而此次奥运会给与了大家一个机会, 去用最少的移动操作改变上面的挂钟的时间全部为12点正(我们只考虑时针). 然而每一次操作并不是任意的, 我们必须按照下面给出的列表对于挂钟进行改变. 每一次操作我们给而且必须给指定的操作挂钟进行, 每一个挂钟顺时针转动90度. 列表如下:

操作指定的操作挂钟
1ABDE
2ABC
3BCEF
4ADG
5BDEFH
6CFI
7DEGH
8GHI
9EFHI

解题思路

这题解法有很多, 但是我们注意到就算穷举运算量也并不大. 于是我们就使用穷举.

有一个简单的”剪枝”, 每一个操作的最大次数为3次(即[0, 4)). 因为当时钟被调整到4次之后又会回到原点, 这显然不是最优解.

遇到的问题

一些非常低级的小问题:

循环变量没有初始化

输出的时候写错了循环变量等

源代码

#include <iostream>

const size_t NUMBER_OF_CLOCKS           = 9;
const size_t NUMBER_OF_OPERATIONS       = 9;
/**
* 最大操作次数.
* 由于操作4次会回到原点, 没有必要继续搜索.
*/
const size_t MAX_NUMBER_OF_OPERATIONS   = 4;

/**
* 获取当前对各个时钟操作的次数.
* @return 对各个时钟操作的次数
*/
int getOperationTimes(int* operations) {
int operationTimes = 0;

for ( size_t i = 0; i < NUMBER_OF_CLOCKS; ++ i ) {
operationTimes += operations[i];
}
return operationTimes;
}

/**
* 获取最优的调整方案
* @param  clocks - 当前每个时钟的时间([0, 4)的整数)
* @param  bestOperations - 对各个时钟最佳操作的次数
* @return 每个操作进行次数的数组
*/
void getBestSolution(int* clocks, int* bestOperations) {
/**
* 存储时钟的初始状态.
* 用于回溯, 在搜索失败后的rollback.
*/
int mirrorClocks[NUMBER_OF_CLOCKS] = {0};

/**
* 存储对时钟的操作.
*/
int operations[NUMBER_OF_OPERATIONS][NUMBER_OF_CLOCKS] = {
{ 1, 1, 0, 1, 1, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 0, 1, 1, 0, 0, 0 },
{ 1, 0, 0, 1, 0, 0, 1, 0, 0 },
{ 0, 1, 0, 1, 1, 1, 0, 1, 0 },
{ 0, 0, 1, 0, 0, 1, 0, 0, 1 },
{ 0, 0, 0, 1, 1, 0, 1, 1, 0 },
{ 0, 0, 0, 0, 0, 0, 1, 1, 1 },
{ 0, 0, 0, 0, 1, 1, 0, 1, 1 }
};

/**
* 存储当前对各时钟操作的计数.
* 记录对每个时钟操作的次数.
*/
int currentOperations[NUMBER_OF_CLOCKS] = {0};

for ( size_t i = 0; i < NUMBER_OF_CLOCKS; ++ i ) {
mirrorClocks[i] = clocks[i];
}

for ( currentOperations[0] = 0 ; currentOperations[0] < MAX_NUMBER_OF_OPERATIONS; ++ currentOperations[0] ) {
for ( currentOperations[1] = 0 ; currentOperations[1] < MAX_NUMBER_OF_OPERATIONS; ++ currentOperations[1] ) {
for ( currentOperations[2] = 0 ; currentOperations[2] < MAX_NUMBER_OF_OPERATIONS; ++ currentOperations[2] ) {
for ( currentOperations[3] = 0 ; currentOperations[3] < MAX_NUMBER_OF_OPERATIONS; ++ currentOperations[3] ) {
for ( currentOperations[4] = 0 ; currentOperations[4] < MAX_NUMBER_OF_OPERATIONS; ++ currentOperations[4] ) {
for ( currentOperations[5] = 0 ; currentOperations[5] < MAX_NUMBER_OF_OPERATIONS; ++ currentOperations[5] ) {
for ( currentOperations[6] = 0 ; currentOperations[6] < MAX_NUMBER_OF_OPERATIONS; ++ currentOperations[6] ) {
for ( currentOperations[7] = 0 ; currentOperations[7] < MAX_NUMBER_OF_OPERATIONS; ++ currentOperations[7] ) {
for ( currentOperations[8] = 0 ; currentOperations[8] < MAX_NUMBER_OF_OPERATIONS; ++ currentOperations[8] ) {
// Rollback
for ( size_t i = 0; i < NUMBER_OF_CLOCKS; ++ i ) {
clocks[i] = mirrorClocks[i];
}

bool isSuccessful = true;
for ( size_t i = 0; i < NUMBER_OF_CLOCKS; ++ i ) {
for ( size_t j = 0; j < NUMBER_OF_OPERATIONS; ++ j ) {
clocks[i] += currentOperations[j] * operations[j][i];
}
clocks[i] %= 4;

if ( clocks[i] != 0 ) {
isSuccessful = false;
break;
}
}

if ( !isSuccessful ) {
continue;
}
// Save the solution
int currentOperationTimes = getOperationTimes(currentOperations);
int bestOperationTimes = getOperationTimes(bestOperations);
if ( currentOperationTimes < bestOperationTimes ) {
for ( size_t i = 0; i < NUMBER_OF_OPERATIONS; ++ i ) {
bestOperations[i] = currentOperations[i];
}
}
}
}
}
}
}
}
}
}
}
}

int main() {
/**
* 存储时钟当前的状态.
* 在搜索时不断改变.
*/
int clocks[NUMBER_OF_CLOCKS] = {0};

/**
* 存储当前对各时钟操作计数的最优解.
*/
int bestOperations[NUMBER_OF_OPERATIONS] = { 10, 10, 10, 10, 10, 10, 10, 10, 10 };

for ( size_t i = 0; i < NUMBER_OF_CLOCKS; ++ i ) {
std::cin >> clocks[i];
}

getBestSolution(clocks, bestOperations);

for ( size_t i = 0; i < NUMBER_OF_OPERATIONS; ++ i ) {
for ( int j = 0; j < bestOperations[i]; ++ j ) {
std::cout << ( i + 1 ) << " ";
}
}
std::cout << std::endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: