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;
}