题目大意:
给出9个表盘和9种表针操作方法,要求找出一个能使所有表针都指向12点的方案。
思路:
用深搜遍历所有可能方案即可,具体思路见代码。
代码:
/* ID: lujunda1 LANG: C++ PROG: clocks */ #include<iostream> #include<stdio.h> #include<queue> #include<cstring> #include<map> using namespace std; struct state //定义结构体来表示当前时钟的状态。mark[]记录各方法使用的数量。 { int clock[3][3]; int mark[9]; }; bool check(state temp) //通过temp的clock[]判断temp状态下的表针是否全部指向12点。 { for(int i=0;i<3;i++) for(int j=0;j<3;j++) if(temp.clock[i][j]%12) return false; return true; } void output(state temp) //输出temp状态下的方法序列。 { bool check=true; for(int i=0;i<9;i++) for(int j=0;j<temp.mark[i];j++) if(check) { printf("%d",i+1); check=false; } else printf(" %d",i+1); printf("\n"); } int operation[9][9]= //operation[][]是9种方法的具体定义。 { {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} }; state op(state temp,int n) //op()方法的含义是,计算temp状态在i方法作用后的结果并返回。 { for(int i=0;i<3;i++) for(int j=0;j<3;j++) if(operation[n][i*3+j]) temp.clock[i][j]+=3; temp.mark[n]++; return temp; } int pos(state temp) //这实际是为避免重复运算而定义的步骤。 //当方法序列为111222334,保证其递归下的序列为1112223344而不是1112223334。 //因为1112223334在111222334之前就已经出现过。 { for(int i=8;i>=0;i--) //返回使用次数不为0且序号最大的方法的序号。 if(temp.mark[i]>0) return i; return 0; } bool dfs(state temp) //深搜 { if(check(temp)) //优先检查temp状态 { output(temp); return true; } for(int i=pos(temp);i<9;i++) if(temp.mark[i]<3&&dfs(op(temp,i))) //temp.mark[i]<3保证了每个方法使用不超过4次,超过4次无意义(指针转了超过一圈)。 return true; return false; } int main() { freopen("clocks.in","r",stdin); freopen("clocks.out","w",stdout); state original; for(int i=0;i<3;i++) for(int j=0;j<3;j++) scanf("%d",&original.clock[i][j]); for(int i=0;i<9;i++) original.mark[i]=0; dfs(original); }