用C++编了个解传统益智游戏华容道的程序,不到1s可给出横刀立马通关步骤。主要用到bfs加上记录已遇到的局面(包括其对称的局面)帮助剪枝。简单修改初始化可解其它初始排布下的华容道。
上图即为横刀立马开局
#include <bits/stdc++.h>
using namespace std;
const int M=5,N=4;
const int caocao_qzIdx=1;
const string NAME[10]={"张飞","曹操","马超","黄忠","关羽","赵云","兵","兵","兵","兵"};
string templateStrMap="";
inline int e(int i,int j)
{
return i*N+j;
}
struct QZ{
int m=1,n=1;
int i=0,j=0;
int type=1,id=0;
string name;
QZ()
{
}
QZ(int _m,int _n,int _i,int _j,int _id=0)
{
m=_m;
n=_n;
i=_i;
j=_j;
if(m==1)
{
if(n==1)
type=1;
else
type=3;
}
else
{
if(n==1)
type=2;
else
type=4;
}
id=_id;
name=NAME[id];
}
void set(int _m,int _n,int _i,int _j)
{
m=_m;
n=_n;
i=_i;
j=_j;
if(m==1)
{
if(n==1)
type=1;
else
type=3;
}
else
{
if(n==1)
type=2;
else
type=4;
}
}
};
struct Move{
int qzIdx,dir;
string lastStrMap;
vector<QZ> lastQZs;
};
map<string,Move> path;
void print(int Map[M][N])
{
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
cout<<Map[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
}
void print(vector<QZ> &QZs)
{
for(int i=0;i<QZs.size();i++)
{
QZ &tmp=QZs[i];
cout<<"i,j:"<<tmp.i<<","<<tmp.j<<" m,n:"<<tmp.m<<","<<tmp.n<<" "<<tmp.type<<endl;
}
}
void print(string &s)
{
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
cout<<int(s[e(i,j)])<<" ";
}
cout<<endl;
}
cout<<endl;
}
struct MAP{
//int Map[M][N]={{2,4,4,2},{2,4,4,2},{2,3,3,2},{2,1,1,2},{1,0,0,1}};//0为空,1为1*1的兵,2为2*1的武将,3为1*2的武将,4为2*2的曹操
string strMap="2442;2442;2332;2112;1001";
vector<QZ> QZs;
int d=0;
MAP()
{
QZs.push_back(QZ(2,1,0,0,0));
QZs.push_back(QZ(2,2,0,1,1));
QZs.push_back(QZ(2,1,0,3,2));
QZs.push_back(QZ(2,1,2,0,3));
QZs.push_back(QZ(1,2,2,1,4));
QZs.push_back(QZ(2,1,2,3,5));
QZs.push_back(QZ(1,1,3,1,6));
QZs.push_back(QZ(1,1,3,2,7));
QZs.push_back(QZ(1,1,4,0,8));
QZs.push_back(QZ(1,1,4,3,9));
}
MAP(string &s,vector<QZ> &_QZs,int _d=0)
{
strMap=s;
QZs=_QZs;
d=_d;
}
void testQZs()
{
int map1[M][N]={0};
for(int i=0;i<QZs.size();i++)
{
QZ &temp=QZs[i];
for(int I=0;I<temp.m;I++)
for(int J=0;J<temp.n;J++)
map1[temp.i+I][temp.j+J]=temp.m+0.1*temp.n;
}
print(map1);
}
//0为左,1为上,2为右,3为下
bool ifmove(int QZ_idx,int dir)
{
QZ &temp=QZs[QZ_idx];
int i=temp.i,j=temp.j,m=temp.m,n=temp.n;
//cout<<"ifmove:"<<i<<" "<<j<<" "<<dir<<endl;
if(dir==0)
{
if(j>0&&strMap[e(i,j-1)]==0)
{
if(temp.m==1||strMap[e(i+1,j-1)]==0)
return true;
}
}
else if(dir==1)
{
if(i>0&&strMap[e(i-1,j)]==0)
{
if(temp.n==1||strMap[e(i-1,j+1)]==0)
return true;
}
}
else if(dir==2)
{
if(m==1)
{
if(n==1)
{
if(j+1<N&&strMap[e(i,j+1)]==0)
return true;
}
else
{
if(j+2<N&&strMap[e(i,j+2)]==0)
return true;
}
}
else
{
if(n==1)
{
if(j+1<N&&strMap[e(i,j+1)]==0&&strMap[e(i+1,j+1)]==0)
return true;
}
else
{
if(j+2<N&&strMap[e(i,j+2)]==0&&strMap[e(i+1,j+2)]==0)
return true;
}
}
}
else
{
if(m==1)
{
if(n==1)
{
if(i+1<M&&strMap[e(i+1,j)]==0)
return true;
}
else
{
if(i+1<M&&strMap[e(i+1,j)]==0&&strMap[e(i+1,j+1)]==0)
return true;
}
}
else
{
if(n==1)
{
if(i+2<M&&strMap[e(i+2,j)]==0)
return true;
}
else
{
if(i+2<M&&strMap[e(i+2,j)]==0&&strMap[e(i+2,j+1)]==0)
return true;
}
}
}
return false;
}
void move(int QZ_idx,int dir)
{
QZ &temp=QZs[QZ_idx];
string &tmpMap=strMap;
for(int i=0;i<temp.m;i++)
for(int j=0;j<temp.n;j++)
{
int I=temp.i+i,J=temp.j+j;
tmpMap[e(I,J)]=0;
}
for(int i=0;i<temp.m;i++)
for(int j=0;j<temp.n;j++)
{
int I=temp.i+i,J=temp.j+j;
if(dir==0)
{
tmpMap[e(I,J-1)]=temp.type;
}
else if(dir==1)
{
tmpMap[e(I-1,J)]=temp.type;
}
else if(dir==2)
{
tmpMap[e(I,J+1)]=temp.type;
}
else
{
tmpMap[e(I+1,J)]=temp.type;
}
}
if(dir==0)
{
temp.j--;
}
else if(dir==1)
{
temp.i--;
}
else if(dir==2)
{
temp.j++;
}
else
{
temp.i++;
}
}
string move2string(int QZ_idx,int dir)
{
QZ &temp=QZs[QZ_idx];
string tmpMap=strMap;
for(int i=0;i<temp.m;i++)
for(int j=0;j<temp.n;j++)
{
int I=temp.i+i,J=temp.j+j;
tmpMap[e(I,J)]=0;
}
for(int i=0;i<temp.m;i++)
for(int j=0;j<temp.n;j++)
{
int I=temp.i+i,J=temp.j+j;
if(dir==0)
{
tmpMap[e(I,J-1)]=temp.type;
}
else if(dir==1)
{
tmpMap[e(I-1,J)]=temp.type;
}
else if(dir==2)
{
tmpMap[e(I,J+1)]=temp.type;
}
else
{
tmpMap[e(I+1,J)]=temp.type;
}
}
//cout<<"finish"<<endl;
return tmpMap;
}
// string genString()
// {
// string s="";
// for(int i=0;i<M;i++)
// {
// for(int j=0;j<N;j++)
// {
// s+=to_string(int(Map[i][j]));
// }
// s+=";";
// }
// return s;
// }
string genString(int _Map[M][N])
{
string s="";
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
s+=int(_Map[i][j]);
}
}
//cout<<"s finish"<<endl;
return s;
}
void genMap(string &s)
{
int Map[M][N]={0};
for(int i=0;i<M;i++)
for(int j=0;j<N;j++)
{
int idx=i*N+j;
Map[i][j]=s[idx];
}
}
// void genQZs()
// {
// int tmpMap[M][N];
// memcpy(tmpMap,Map,sizeof(Map));
// int I=0;
// for(int i=0;i<M;i++)
// for(int j=0;j<N;j++)
// {
// if(tmpMap[i][j]==2)
// {
// tmpMap[i+1][j]=-2;
// QZs[I++].set(2,1,i,j);
// }
// else if(tmpMap[i][j]==4)
// {
// tmpMap[i][j+1]=-4;
// tmpMap[i+1][j+1]=-4;
// tmpMap[i+1][j]=-4;
// QZs[I++].set(2,2,i,j);
// caocao_qzIdx=I-1;
// }
// else if(tmpMap[i][j]==3)
// {
// tmpMap[i][j+1]=-3;
// QZs[I++].set(1,2,i,j);
// }
// else if(tmpMap[i][j]==1)
// {
// QZs[I++].set(1,1,i,j);
// }
// }
// }
bool ifEnd()
{
QZ &temp=QZs[caocao_qzIdx];
if(temp.i==3&&temp.j==1)
return true;
return false;
}
}mymap;
string mirror(string &s)
{
string s1=s;
for(int i=0;i<M;i++)
for(int j=0;j<N;j++)
{
s1[e(i,N-j-1)]=s[e(i,j)];
}
return s1;
}
string genResStr(vector<QZ> &QZs)
{
string s=templateStrMap;
for(int I=0;I<QZs.size();I++)
{
QZ &q=QZs[I];
int i=q.i,j=q.j;
if(q.type==1)
{
s.replace(i*(2*N+1)+2*j,2,"兵");
}
else if(q.type==2)
{
s.replace(i*(2*N+1)+2*j,2,q.name.substr(0,2));
s.replace((i+1)*(2*N+1)+2*j,2,q.name.substr(2,2));
}
else if(q.type==3)
{
s.replace(i*(2*N+1)+2*j,2,q.name.substr(0,2));
s.replace(i*(2*N+1)+2*(j+1),2,q.name.substr(2,2));
}
else
{
s.replace(i*(2*N+1)+2*j,4,q.name);
s.replace((i+1)*(2*N+1)+2*j,4,q.name);
}
}
return s;
}
void writeRes(vector<Move> &resPath)
{
ofstream wr;
wr.open("hrd_out.txt",ios::app);
for(int i=resPath.size()-1;i>=0;i--)
{
Move &m=resPath[i];
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
}
wr<<endl;
}
}
}
string bfs()
{
queue<MAP> q;
q.push(mymap);
unordered_set<string> visited;
visited.insert(mymap.strMap);
int D=0;
while(!q.empty())
{
MAP tmpNode=q.front();
string &s0=tmpNode.strMap;
//print(s0);
vector<QZ> &QZs=tmpNode.QZs;
//print(QZs);
int d=tmpNode.d;
q.pop();
if(d>D)
{
D=d;
cout<<d<<endl;
}
if(tmpNode.ifEnd())
{
return s0;
}
for(int i=0;i<QZs.size();i++)
{
QZ &temp=QZs[i];
//cout<<"i="<<i<<endl;
for(int dir=0;dir<4;dir++)
{
//cout<<"dir"<<dir<<endl;
if(tmpNode.ifmove(i,dir))
{
//cout<<temp.i<<" "<<temp.j<<" "<<dir<<endl;
//mymap.move(i,dir);
string s1=tmpNode.move2string(i,dir);
//cout<<"next"<<endl;
if(!visited.count(s1))
{
//cout<<"next0"<<endl;
visited.insert(s1);
visited.insert(mirror(s1));
path[s1]={i,dir,s0,QZs};
MAP map1(s1,QZs,d+1);
QZ &temp1=map1.QZs[i];
if(dir==0)
{
temp1.j--;
}
else if(dir==1)
{
temp1.i--;
}
else if(dir==2)
{
temp1.j++;
}
else
{
temp1.i++;
}
if(map1.ifEnd())
{
return s1;
}
q.push(map1);
//cout<<s1<<endl;
//cout<<"next1"<<endl;
}
}
}
}
}
}
int main()
{
cout<<"huarongdao"<<endl;
//mymap.testQZs();
int Map[M][N]={{2,4,4,2},{2,4,4,2},{2,3,3,2},{2,1,1,2},{1,0,0,1}};
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
mymap.strMap[e(i,j)]=Map[i][j];
templateStrMap+=" ";
}
templateStrMap+="\n";
}
//string s1="2442;2442;2332;2112;0110";
//mymap.strMap=s1;
//mymap.genMap(mymap.strMap);
//mymap.genQZs();
print(mymap.strMap);
cout<<endl;
cout<<templateStrMap;
cout<<genResStr(mymap.QZs)<<endl;
// for(int I=0;I<2;I++)
// for(int i=0;i<mymap.QZs.size();i++)
// {
// QZ &temp=mymap.QZs[i];
// for(int dir=0;dir<4;dir++)
// {
//
// if(mymap.ifmove(i,dir))
// {
// cout<<temp.i<<" "<<temp.j<<" "<<dir<<endl;
// mymap.move(i,dir);
//
// print(mymap.strMap);
// print(mymap.QZs);
// cout<<endl;
// }
// }
// }
string s=bfs();
print(s);
vector<Move> resPath;
while(path.count(s))
{
resPath.push_back(path[s]);
s=path[s].lastStrMap;
}
for(int i=resPath.size()-1;i>=0;i--)
{
cout<<genResStr(resPath[i].lastQZs)<<endl;
}
return 0;
}