# USACO: clocks

755人阅读 评论(0)

Consider nine clocks arranged in a 3x3 array thusly:
|-------|    |-------|    |-------|    |       |    |       |    |   |   |    |---O   |    |---O   |    |   O   |          |       |    |       |    |       |           |-------|    |-------|    |-------|        A            B            C|-------|    |-------|    |-------||       |    |       |    |       ||   O   |    |   O   |    |   O   ||   |   |    |   |   |    |   |   ||-------|    |-------|    |-------|    D            E            F|-------|    |-------|    |-------||       |    |       |    |       ||   O   |    |   O---|    |   O   ||   |   |    |       |    |   |   ||-------|    |-------|    |-------|    G            H            I

The goal is to find a minimal sequence of moves to return all the dials to 12 o'clock. Nine different ways to turn the dials on the clocks are spplied via a table below; each way is called a move. Select for each move a number 1 through 9 which will cause the dials of the affected clocks (see next table) to be turned 90 degrees clockwise.

 Move Affected clocks 1 ABDE 2 ABC 3 BCEF 4 ADG 5 BDEFH 6 CFI 7 DEGH 8 GHI 9 EFHI

### Example

Each number represents a time accoring to following table:
9 9 12       9 12 12       9 12 12        12 12 12      12 12 12 6 6 6  5 ->  9  9  9  8->  9  9  9  4 ->  12  9  9  9-> 12 12 12 6 3 6        6  6  6       9  9  9        12  9  9      12 12 12

[But this might or might not be the correct' answer; see below.]

### INPUT FORMAT

 Lines 1-3: Three lines of three space-separated numbers; each number represents the start time of one clock, 3, 6, 9, or 12. The ordering of the numbers corresponds to the first example above.

### SAMPLE INPUT (file clocks.in)

9 9 126 6 66 3 6

### OUTPUT FORMAT

A single line that contains a space separated list of the shortest sequence of moves (designated by numbers) which returns all the clocks to 12:00. If there is more than one solution, print the one which gives the lowest number when the moves are concatenated (e.g., 5 2 4 6 < 9 3 1 1).

4 5 8 9`

### 分析

1. 由于每种移动方法最多出现三次，故用一个32位整数就可以表示当前的移动方法（用9×3个bit）。
2. 利用递归进行穷举的时候，可以剪枝来减小穷举的量。

#include <stdio.h>
#include <assert.h>

int rules[10][9] = { {0,0,0,0,0,0,0,0,0}, {3,3,0,3,3,0,0,0,0}, {3,3,3,0,0,0,0,0,0},
{0,3,3,0,3,3,0,0,0}, {3,0,0,3,0,0,3,0,0}, {0,3,0,3,3,3,0,3,0},
{0,0,3,0,0,3,0,0,3}, {0,0,0,3,3,0,3,3,0}, {0,0,0,0,0,0,3,3,3},
{0,0,0,0,3,3,0,3,3}};

int getMinMoves(int clocks[9], int rule, int curMove);
void print(FILE* fout, int minMove);

int main(void)
{
int clocks[9];
int i;
int min_moves;
FILE* fin = fopen("clocks.in", "r");
FILE* fout = fopen("clocks.out", "w");
assert(fin != NULL && fout != NULL);

for (i = 0; i < 9; i ++)
{
fscanf(fin, "%d", clocks+i);
if (clocks[i] == 12)
{
clocks[i] = 0;//for arithmetic convenience
}
}

min_moves = getMinMoves(clocks, 1, 0);

print(fout, min_moves);
fclose(fin);
fclose(fout);
return 0;
}

int getMinMoves(int clocks[9], int rule, int curMove)
{
int tempMove = 0;//record the search result of the subtree
int minMove = 1 << 29;//record the mini of search results, initially set to a big value
int curClocks[9];//current clocks
int i,j;

memcpy(curClocks, clocks, sizeof(int)*9);
for (i = 0; i < 4; i ++) // at most move 3 times according to curren rule
{
if ( i != 0)//if move clocks according to the current rule
{
curMove = curMove | (1 << ((rule -1)*3 + i - 1));
for (j = 0; j < 9; j ++)
{
curClocks[j] = (clocks[j] + rules[rule][j] * i) % 12;
}
}

for (j = 0; j < 9 && curClocks[j] == 0; j ++)
{
}
if (j == 9)
{
return curMove;//if found in current rule, then update
}

if (rule < 9) // if not the last rule (9), then search the subtree
{
tempMove = getMinMoves(curClocks, rule + 1, curMove);
if ((tempMove > 0) && (tempMove < minMove))
{
minMove = tempMove;
}
}
}

//if not results from the current search, then check the result from subtree
if (rule == 9)
{
return 0;// last rule, so nothing found
}
else{
if (minMove == (1 << 29))
{
return 0;// keep unchanged, nothing found
}
else{
return minMove;
}
}
};

void print(FILE* fout, int minMove)
{
int i = 0;
int j = 1;
int found = 0;
do
{
if (j & minMove)
{
if (found)
{
fprintf(fout, " ");
}
fprintf(fout, "%d", i / 3 + 1);
found = 1;
}
j = j << 1;
i ++;
} while (i < 27);
fprintf(fout, "/n");
}

0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：992次
• 积分：18
• 等级：
• 排名：千里之外
• 原创：1篇
• 转载：0篇
• 译文：0篇
• 评论：0条
文章分类
文章存档
阅读排行
评论排行