题意:9个钟,指针只能有4种情况(3,6,9,12)。有9种操作,每种都使9个钟中的特定几个走3个小时。给定初始状态,求最快使9个钟都指向12点的方案。(9种操作按1-9编号,最快的方案代表编号最小的方案,如1122<2233)
解题思路:
- 位运算加速,每个钟用3位2进制数表示,000代表指向3点,001代表指向6点,010代表指向9点,011代表指向12点。走3个小时即最低位+1,然后最高位清零防止进位的影响
- DFS,参考http://blog.sina.com.cn/s/blog_4e4c6ca501000ct0.html
代码:
/*
ID: zc.rene1
LANG: C
PROG: clocks
*/
#include<stdio.h>
#include<string.h>
#define ALL_12 0x036DB6DB
int clock=0x00000000, min_len=30;
int ans[30], way[30], use[10];
int clock_plus[9]={0x00001209, 0x00000049, 0x00009048,
0x00040201, 0x00209208, 0x01008040,
0x00241200, 0x01240000, 0x01209000};
int clock_and[9]={0xFFFFB7DB, 0xFFFFFEDB, 0xFFFDBEDF,
0xFFEFF7FB, 0xFF7DB7DF, 0xFBFDFEFF,
0xFF6FB7FF, 0xFB6FFFFF, 0xFB7DBFFF};
void dfs(int len){
int i, j, k, temp_clock=clock;
if(len>min_len) return ;
if(clock==ALL_12){
min_len=len-1;
memcpy(ans, way, (len)*sizeof(int));
return ;
}
for(i=way[len-1]; i<=9; i++){
if(use[i]>=3) continue;
clock+=clock_plus[i-1];
clock&=clock_and[i-1];
use[i]++;
way[len]=i;
dfs(len+1);
clock=temp_clock;
use[i]--;
}
}
int main(void){
FILE *fin=fopen("clocks.in", "r");
FILE *fout=fopen("clocks.out", "w");
int num, i;
for(i=0; i<9; i++){
fscanf(fin, "%d", &num);
clock+=((num/3-1)<<(3*i));
}
memset(use, 0, 10*sizeof(int));
memset(way, 0, 30*sizeof(int));
way[0]=1;
dfs(1);
for(i=1; i<min_len; i++){
fprintf(fout, "%d ", ans[i]);
}
fprintf(fout, "%d\n", ans[min_len]);
return 0;
}