Ural 1016. Cube on the Walk (bfs滾骰子)

題意:個立方體放在國際象棋棋盤的一個格子上,該立方體每一面都和棋盤的格子一樣大。該立方體每一面都標有一個非負整數。你可以在棋盤上滾動該立方體,在這期間計算立方體底面數字的和。你的任務是找出一條從給定的起點到終點的路徑,使得前面所說的和最小。

比較麻煩的題。

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


發佈了202 篇原創文章 · 獲贊 6 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章