简单的用宽度优先搜索。状态空间的大小为4^9,性能上是可以接受的。考虑到每个时钟只有3,6,9,12四种状态,且目标状态为12,可将其转化为1230,这样,9个时钟可以放在一个整数的18位中,比较状态只需比较两个整数是否相等,而目标状态为0,更容易判断。
调试过程:turn函数中漏掉了cur >>= 2;导致状态不正确。
原题链接:
http://ace.delos.com/usacoprob2?a=1N7165lJnJE&S=clocks
/*
ID: blackco3
TASK: clocks
LANG: C++
*/
#include <fstream>
#include <iostream>
#include <stdlib.h>
#include <memory.h>
#define _max_states_ 1<<18
using namespace std ;
int trans[9][9] = {
/* A B C D E F G H I */
{1, 1, 0, 1, 1, 0, 0, 0, 0 }, //ABDE
{1, 1, 1, 0, 0, 0, 0, 0, 0 }, //ABC
{0, 1, 1, 0, 1, 1, 0, 0, 0 }, //BCEF
{1, 0, 0, 1, 0, 0, 1, 0, 0 }, //ADG
{0, 1, 0, 1, 1, 1, 0, 1, 0 }, //BDEFH
{0, 0, 1, 0, 0, 1, 0, 0, 1 }, //CFI
{0, 0, 0, 1, 1, 0, 1, 1, 0 }, //DEGH
{0, 0, 0, 0, 0, 0, 1, 1, 1 }, //GHI
{0, 0, 0, 0, 1, 1, 0, 1, 1 }, //EFHI
};
int queue[_max_states_];
int visited[_max_states_];
struct t_trace{
t_trace *pre ;
int trans ;
} trace[_max_states_];
int source ;
void show_trace( ofstream &fout, t_trace *p_trace )
{
if( p_trace->pre-trace==source ){
fout << p_trace->trans ;
return ;
}
show_trace(fout, p_trace->pre );
fout << " " << p_trace->trans ;
}
int turn( int cur, int tno )
{
int tmp, res=0 ;
for( int i=0; i<9; i++){
tmp = cur & 0x3 ;
tmp = trans[tno][i] ? (tmp+1)&0x3 : tmp ;
res |= tmp<<(i<<1);
cur >>= 2 ;
}
return res ;
}
int main() {
ofstream fout ("clocks.out");
ifstream fin ("clocks.in");
source=0;
for( int i=0, tmp=0; i<9; i++ ){
fin >> tmp ;
source |= ((tmp/3)&0x3)<<(i<<1) ;
}
memset( visited, 0, sizeof(visited) );
int *head=queue, *tail=queue;
*(tail++)=source , visited[source]=1 ;
int next, unfound=1 ;
do{
for( int i=0; i<9; i++ ){
next=turn(*head, i);
if( visited[next] )
continue ;
visited[next]=1;
*(tail++)=next ;
trace[next].pre=trace+*head, trace[next].trans=i+1;
if( !next ){
unfound=0 ;
break ;
}
}
}while((++head)!=tail && unfound );
show_trace(fout, trace);
fout << endl ;
return 0;
}