1题目描述
英文: http://ace.delos.com/usacoprob2?a=2dcMjFnNl7S&S=clocks
中文翻译: http://www.nocow.cn/index.php/Translate:USACO/clocks
2深度优先搜索解法
2.1 思路:用二进制的三位保存一个时钟的状态。低两位表示四种状态,第三位用作进位,每次操作后置零[1][2]
2.2 代码:
/*
ID: wangsiy1
LANG: C
TASK: clocks
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEBUG 1
/* 移动方法编号是way的下标加一 */
int way[9] = {
/*00A00B00C00D00E00F00G00H00I */
0b001001000001001000000000000, /* 1 */
0b001001001000000000000000000, /* 2 */
0b000001001000001001000000000, /* 3 */
0b001000000001000000001000000, /* 4 */
0b000001000001001001000001000, /* 5 */
0b000000001000000001000000001, /* 6 */
0b000000000001001000001001000, /* 7 */
0b000000000000000000001001001, /* 8 */
0b000000000000001001000001001, /* 9 */
};
int afteradd = 0b00000011011011011011011011011011;
int cantakethis(int *path, int i, int depth)
{
int m, r=0;
for(m=0; m<depth; m++) {
if(path[m]==i)
++r;
}
if (r>=3) return 0;
else return 1;
}
void printresult(int *path, int depth)
{
int i;
FILE *fout = fopen ("clocks.out", "w");
for(i=0; i<depth; i++) {
fprintf(fout, "%d", path[i]);
if(i==depth-1)
fprintf(fout, "\n");
else
fprintf(fout, " ");
}
}
/* state初始为0 */
void readdata(FILE *fin, int *state)
{
int c, i;
for(i=0; i<9; i++) {
fscanf(fin, "%d", &c);
(*state) <<= 3;
if(c==12)
c = 0;
else if (c==3)
c = 1;
else if (c==6)
c = 2;
else if (c==9)
c = 3;
*state |= c;
}
}
void dfs(int depth, int state, int *path)
{
int i, firstway, tmpstate;
if(state==0) {
printresult(path, depth);
}
else {
if(depth > 0)
firstway = path[depth-1];
else
firstway = 1;
/* i 方法编号,既下标加一 */
for(i=firstway; i<=9; i++) {
if (cantakethis(path, i, depth)) {
tmpstate = state;
state += way[i-1];
state &= afteradd;
path[depth] = i;
/* printresult(path, depth); */
dfs(depth+1, state, path);
state = tmpstate;
}
}
}
}
main ()
{
/* path[]记录方法步骤,depth为递归深度,同时为depth的最后一个元素下标 */
int state=0, path[27], depth=0;
char s[32];
FILE *fin = fopen ("clocks.in", "r");
readdata(fin, &state);
/* printf("%d\n", state); */
dfs(0, state, path);
exit (0);
}
2.3 执行结果
Executing... Test 1: TEST OK [0.027 secs, 1972 KB] Test 2: TEST OK [0.027 secs, 1972 KB] Test 3: TEST OK [0.027 secs, 1972 KB] Test 4: TEST OK [0.027 secs, 1972 KB] Test 5: TEST OK [0.027 secs, 1972 KB] Test 6: TEST OK [0.027 secs, 1972 KB] Test 7: TEST OK [0.027 secs, 1972 KB] Test 8: TEST OK [0.027 secs, 1972 KB] Test 9: TEST OK [0.027 secs, 1972 KB]
3广度优先搜索解法
3.1广搜的队列最大长度为 4^9=262144 [1]
3.2代码
/*
ID: wangsiy1
LANG: C
TASK: clocks
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEBUG 0
#define QLEN 262144
typedef struct {
int state;
char path[27], len;
} clock;
/* 移动方法编号是way的下标加一 */
int way[9] = {
/*00A00B00C00D00E00F00G00H00I */
0b001001000001001000000000000, /* 1 */
0b001001001000000000000000000, /* 2 */
0b000001001000001001000000000, /* 3 */
0b001000000001000000001000000, /* 4 */
0b000001000001001001000001000, /* 5 */
0b000000001000000001000000001, /* 6 */
0b000000000001001000001001000, /* 7 */
0b000000000000000000001001001, /* 8 */
0b000000000000001001000001001, /* 9 */
};
int afteradd = 0b00000011011011011011011011011011;
int cantakethis(clock *t, int i)
{
int m, r=0, depth = t->len;
for(m=0; m<depth; m++) {
if(t->path[m]==i)
++r;
}
if (r>=3) return 0;
else return 1;
}
void printresult(clock *t)
{
int i, len;
FILE *fout = fopen ("clocks.out", "w");
len = t->len;
for(i=0; i<len; i++) {
fprintf(fout, "%hd", t->path[i]);
if(i==len-1)
fprintf(fout, "\n");
else
fprintf(fout, " ");
}
}
/* state初始为0 */
void readdata(FILE *fin, int *state)
{
int c, i;
for(i=0; i<9; i++) {
fscanf(fin, "%d", &c);
(*state) <<= 3;
if(c==12)
c = 0;
else if (c==3)
c = 1;
else if (c==6)
c = 2;
else if (c==9)
c = 3;
*state |= c;
}
}
void cpyclock(clock *from, clock *to)
{
int i;
to->state = from->state;
to->len = from->len;
for(i=0; i<from->len; i++)
to->path[i] = from->path[i];
}
void dequeue(clock *queue, clock *tmp, int *head)
{
cpyclock(queue+*head, tmp);
(*head) = (++(*head)) % QLEN;
}
void enqueue(clock *queue, clock *tmp2, int *tail)
{
cpyclock(tmp2, queue+*tail);
*tail = (++(*tail)) % QLEN;
}
void bfs(int state)
{
int head, tail, len, startway, i, j ;
clock queue[QLEN], *tmp, *tmp2;
tmp = (clock *) malloc (sizeof(clock));
tmp2 = (clock *) malloc (sizeof(clock));
queue[0].state=state;
queue[9].len = 0;
head = 0;
tail = 1;
while(head != tail) {
dequeue(queue, tmp, &head);
if(tmp->state == 0) {
printresult(tmp);
return;
}
if(tmp->len>0)
startway = tmp->path[tmp->len-1];
else
startway = 1;
for(i=startway; i<=9; i++) {
if (cantakethis(tmp, i)) {
tmp2->state = tmp->state + way[i-1];
tmp2->state &= afteradd;
tmp2->len = tmp->len + 1;
for(j=0; j<= tmp->len; j++)
tmp2->path[j] = tmp->path[j];
tmp2->path[tmp2->len - 1] = i;
#if DEBUG
/* printf("state: %d", tmp2->state); */
/* printf("path:"); */
/* printresult(tmp2); */
printf("len :%d\n", tmp2->len);
#endif
if(tmp2->state == 0) {
printresult(tmp2);
return;
}
else
enqueue(queue, tmp2, &tail);
}
}
}
}
main ()
{
/* times操作次数 */
int state=0, path[27], times=0;
char s[32];
FILE *fin = fopen ("clocks.in", "r");
readdata(fin, &state);
/* printf("%d\n", state); */
bfs(state);
exit (0);
}
3.3执行结果
Executing... Test 1: TEST OK [0.000 secs, 10044 KB] Test 2: TEST OK [0.000 secs, 10040 KB] Test 3: TEST OK [0.000 secs, 10036 KB] Test 4: TEST OK [0.000 secs, 10044 KB] Test 5: TEST OK [0.000 secs, 10040 KB] Test 6: TEST OK [0.054 secs, 10040 KB] Test 7: TEST OK [0.054 secs, 10040 KB] Test 8: TEST OK [0.054 secs, 10044 KB] Test 9: TEST OK [0.054 secs, 10044 KB]
参考文献:
[1] http://www.nocow.cn/index.php/USACO/clocks
[2] http://blog.csdn.net/pennyshe/archive/2011/02/27/6211780.aspx