IDA-star深搜+模拟标记法+剪枝
题目:回转游戏
Code:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int ti;//times 次数(IDA star)
int g[100];
int odr[8][7]={
{1,3,7,12,16,21,23},
{2,4,9,13,18,22,24},
{11,10,9,8,7,6,5},
{20,19,18,17,16,15,14},
{24,22,18,13,9,4,2},
{23,21,16,12,7,3,1},
{14,15,16,17,18,19,20},
{5,6,7,8,9,10,11}
};//把图中的点依次标记为1-24,所得到的,ABCDEFGH分别对应的操作序列
int cir[8]={7,8,9,13,18,17,16,12};//中间8个数的序列
int price(){//估价函数
int c1=0,c2=0,c3=0;
for(int i=0;i<8;i++)
if(g[cir[i]]==1)c1++;
else if(g[cir[i]]==2)c2++;
else c3++;
int ma=max(max(c1,c2),c3);
return (8-ma);
}
bool check(){//判断当前是否已经满足题意
for(int i=0;i<7;i++)
if(g[cir[i]]!=g[cir[i+1]])
return false;
return true;
}
void move(int i){//操作函数
int tmp=g[odr[i][0]];
for(int j=1;j<7;j++){
g[odr[i][j-1]]=g[odr[i][j]];
}
g[odr[i][6]]=tmp;
}
int oppo[8]={5,4,7,6,1,0,3,2};//剪枝用,成对操作
bool dfs(int u,int last,string res){//深搜过程
if(u+price()>ti)return false;
if(check()){
cout<<res<<endl;
cout<<g[7]<<endl;
return true;}
for(int i=0;i<8;i++){
if(oppo[i]==last)continue;
move(i);
if(dfs(u+1,i,res+(char)('A'+i)))return true;
move(oppo[i]);
}
return false;
}
int main(){
while(cin>>g[1]){
ti=0;
if(g[1]==0)break;
for(int i=2;i<=24;i++)cin>>g[i];
if(check()){
puts("No moves needed");
cout<<g[7]<<endl;
}
else
while(true){
++ti;
if(dfs(0,-1,""))break;
}
}
}
一遍写对我真实太开心了hh
浙公网安备 33010602011771号