題意:個立方體放在國際象棋棋盤的一個格子上,該立方體每一面都和棋盤的格子一樣大。該立方體每一面都標有一個非負整數。你可以在棋盤上滾動該立方體,在這期間計算立方體底面數字的和。你的任務是找出一條從給定的起點到終點的路徑,使得前面所說的和最小。
比較麻煩的題。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<fstream>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
const ll d6=1023,d5=d6<<10,d4=d5<<10,d3=d4<<10,d2=d3<<10,d1=d2<<10;
#define tl(x) ((x&d1)|(x&d2)|(x&d4)<<10|(x&d5)<<10|(x&d6)<<10|(x&d3)>>30)
#define tr(x) ((x&d1)|(x&d2)|(x&d6)<<30|(x&d3)>>10|(x&d4)>>10|(x&d5)>>10)
#define tu(x) ((x&d5)<<40|(x&d3)<<10|(x&d1)>>20|(x&d4)|(x&d2)>>30|(x&d6))
#define td(x) ((x&d3)<<20|(x&d5)<<30|(x&d2)>>10|(x&d4)|(x&d1)>>40|(x&d6))
map<ll,int>mm;
struct Nod
{
int x,y,d;
ll s;
Nod() {}
Nod(int x,int y,int d,ll s):x(x),y(y),d(d),s(s) {}
bool operator < (const Nod &p)const{return d>p.d;}
};
int d[10][10][30];
bool vis[10][10][30];
Nod pre[10][10][30];
int dx[]= {0,-1,0,1};
int dy[]= {-1,0,1,0}; //d l u r
int dij(int sx,int sy,ll ss,int tx,int ty,ll &ts)
{
priority_queue<Nod>q;
d[sx][sy][mm[ss]]=(ss&d5)>>10;
q.push(Nod(sx,sy,(ss&d5)>>10,ss));
int ux,uy,ud,vx,vy,vd;
ll us,vs;
while(!q.empty())
{
ux=q.top().x;uy=q.top().y;
ud=q.top().d;us=q.top().s;
q.pop();
if(ux==tx&&uy==ty){ts=us;return ud;}
if(vis[ux][uy][mm[us]]) continue;
vis[ux][uy][mm[us]]=1;
for(int i=0; i<4; i++)
{
vx=ux+dx[i];vy=uy+dy[i];
if(vx<1||vx>8||vy<1||vy>8) continue;
if(i==0) vs=td(us);
if(i==1) vs=tl(us);
if(i==2) vs=tu(us);
if(i==3) vs=tr(us);
vd=ud+((vs&d5)>>10);
if(vd<d[vx][vy][mm[vs]])
{
d[vx][vy][mm[vs]]=vd;
q.push(Nod(vx,vy,vd,vs));
pre[vx][vy][mm[vs]]=Nod(ux,uy,mm[us],0);
}
}
}
}
void path(Nod p)//print path
{
if(p.x==-1) return;
path(pre[p.x][p.y][p.d]);
printf(" %c%c",p.x+96,p.y+48);
}
int main()
{
memset(d,63,sizeof(d));
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
char a,b,c,f;
ll e[6];
cin>>a>>b>>c>>f;
a-=96,b-=48,c-=96,f-=48;
for(int i=0; i<6; i++) cin>>e[i];
ll st,x=e[0]<<50|e[1]<<40|e[2]<<30|e[3]<<20|e[4]<<10|e[5],xx=x;
int i,j,k,cnt=0;
for(i=0; i<4; i++,xx=tl(xx))
for(j=0; j<4; j++,xx=tu(xx))
for(k=0; k<4; k++,xx=tl(xx))
if(mm.find(xx)==mm.end()) mm[xx]=cnt++;//find all states
cout<<dij(a,b,x,c,f,st);
path(Nod(c,f,mm[st],0));
return 0;
}