给你一张完全图,每条边有一种颜色,有三个石头,能把一个石头从一个点a移动到b的条件是:1、没有石头在b上。2、a,b边的颜色和另两块石头所在点连边的颜色相同。现在要把这三个石头移动到1,2,3号点,问最少移动多少步?
思路:这道题目看起来有点复杂,仔细想想这就是一个最短路问题(三维最短路),也可以理解为一种图上的dp,用用三元组(i,j,k)第一块石头在i点,第二个在j,第三个在k的状态,状态总数为70*70*70,然后d[i][j][k]表示把三个石头从初始状态移动到状态(i,j,k)时所需要的最少步数,也可以理解为这个三维图上的距离。写的时候按照dijkstra算法去写就可以了,向外拓展时注意判定条件,更新时需要维护路径。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<iostream>
#define INF 1<<30
using namespace std;
struct node
{
int x,y,z,d;
bool operator <(const node &rhs)const
{
return d>rhs.d;
}
}fa[80][80][80];
struct NODE
{
int from,to;
};
char s[80][80];int n,d[80][80][80];
bool done[80][80][80];
priority_queue<node>q;
node makenode(int x,int y,int z,int d)
{
node res;
res.x=x;res.y=y;res.z=z;res.d=d;
return res;
}
void dij(int s1,int s2,int s3)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
d[i][j][k]=INF;
d[s1][s2][s3]=0;
memset(done,0,sizeof(done));
node tmp;tmp.x=s1;tmp.y=s2;tmp.z=s3;tmp.d=0;q.push(tmp);
while(!q.empty())
{
tmp=q.top();
q.pop();
int x=tmp.x,y=tmp.y,z=tmp.z,D=tmp.d;
if(done[x][y][z])
continue;
done[x][y][z]=1;
for(int i=1;i<=n;i++)
if(i!=y&&i!=x&&i!=z)
{
node u;
if(s[x][i]==s[y][z]&&D+1<d[i][y][z])
{
fa[i][y][z]=tmp;
d[i][y][z]=D+1;
u=makenode(i,y,z,D+1);
q.push(u);
}
if(s[y][i]==s[x][z]&&D+1<d[x][i][z])
{
fa[x][i][z]=tmp;
d[x][i][z]=D+1;
u=makenode(x,i,z,D+1);
q.push(u);
}
if(s[z][i]==s[x][y]&&D+1<d[x][y][i])
{
fa[x][y][i]=tmp;
d[x][y][i]=D+1;
u=makenode(x,y,i,D+1);
q.push(u);
}
}
}
}
NODE makeNODE(int fx,int fy,int fz,int x,int y,int z)
{
NODE res;
if(fx!=x)
res.from=fx,res.to=x;
if(fy!=y)
res.from=fy,res.to=y;
if(fz!=z)
res.from=fz,res.to=z;
return res;
}
int main()
{
scanf("%d",&n);
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
dij(x,y,z);
int ans=INF,u,v,w;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
for(int k=1;k<=3;k++)
if(i!=j&&i!=k&&j!=k)
if(ans>d[i][j][k])
ans=d[i][j][k],u=i,v=j,w=k;
if(ans<INF)
{
printf("%d\n",ans);
stack<NODE>stk;
while(x!=u||y!=v||z!=w)
{
NODE tmp=makeNODE(fa[u][v][w].x,fa[u][v][w].y,fa[u][v][w].z,u,v,w);
int nx=fa[u][v][w].x;
int ny=fa[u][v][w].y;
int nz=fa[u][v][w].z;
u=nx,v=ny,w=nz;
stk.push(tmp);
}
while(!stk.empty())
{
NODE tmp=stk.top();
printf("%d %d\n",tmp.from,tmp.to);
stk.pop();
}
}
else printf("-1");
}