4次同一操作等效于没有操作,操作的顺序不影响结果。
用迭代加深搜索解(貌似效率不高),代码如下:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
ifstream fin("clocks.in");
ofstream fout("clocks.out");
#ifdef _DEBUG
#define out cout
#define in cin
#else
#define out fout
#define in fin
#endif
//op[i][j]为操作i对第j个时钟增加的小时数
int ops[9][9];
string op[9] = {
"ABDE","ABC","BCEF","ADG","BDEFH","CFI","DEGH","GHI","EFHI"
};
//clocks当前时钟的状态
int clocks[9];
//当前的操作序列
int cur_ops[9];
void pre()
{
memset(ops,0,sizeof(ops) );
memset(cur_ops,0,sizeof(cur_ops));
for(int i=0;i<9;++i){
for(int j=0;j<op[i].size();++j){
ops[i][op[i][j]-'A'] = 3;
}
}
}
//执行clocks操作序列
void do_ops()
{
for(int i=0;i<9;++i){
if(cur_ops[i]!=0)
for(int j=0;j<9;++j){
clocks[j]+=ops[i][j]*cur_ops[i];
clocks[j]%=12;
}
}
}
//i为当前到达的操作编号
void dfs(int i, int cur_depth,int max_dep)
{
//到达迭代加深搜索的最大深度或i超过最大
if(cur_depth>max_dep||i>9)
return;
if(cur_depth==max_dep){
//保存当前clocks状态
int saved[9];
memcpy(saved,clocks,sizeof(clocks));
do_ops();
bool valid = true;
for(int i=0;i<9;++i){
if(clocks[i]!=0){
valid = false;
break;
}
}
if(valid){
//时钟全为0,到达可行解
bool first = true;
for(int i=0;i<9;++i){
if(cur_ops[i]!=0){
int t = cur_ops[i];
while(t--){
if(first){
out<<i+1;
first = false;
}else{
out<<" "<<i+1;
}
}
}
}
out<<endl;
exit(0);
}else{
//恢复时钟
memcpy(clocks,saved,sizeof(saved));
return;
}
}
for(int inc=3;inc>=0;inc--){
//因为要求最小的序列,优先多分配当前i,再分配后续更大的号
if(cur_depth+inc<=max_dep&&cur_ops[i]+inc<4){
cur_ops[i]+=inc;
dfs(i+1,cur_depth+inc,max_dep);
cur_ops[i]-=inc;
}
}
}
void solve()
{
pre();
for(int i=0;i<9;++i){
in>>clocks[i];
clocks[i]%=12;
}
for(int d = 0;d<=3*9;++d){
dfs(0,0,d);
}
}
int main(int argc,char *argv[])
{
solve();
return 0;
}