翻转方块问题

dy上的小游戏:将海绵宝宝翻转过来,从头朝下,变为,头朝上

问题普遍化

方块有六个面,记面和序号的映射:前1,后3,上2,下4,左6,右5, 初始时,输入地图大小n ,则地图为nxn 输入方块的初始位置和特殊图案所在的面,例如1 1 1 ,表示,方块在(1,1)位置,特殊的面在前面 输入方块需要达到的状态:例如1 1 5,表示,方块在(1,1)位置,特殊的面在右面 请程序输出,通过怎么样的翻转,能从初始状态达到目标状态,并输出翻转方法

对于举的例子,方法为:右,下,左,上

解决方法

思路:使用bfs求最短路径

注意点:1.将下一步的x,y变化量存为数组dx和dy,将下一步面朝的方向也用数组保存

2.将初始距离设置为很大的值(INF)

3.回溯路径:记录当前状态是从哪一状态转移而来的,记录转移的方向变化

#include <iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
using namespace std;

const int maxn=105;
int dist[maxn][maxn][10],dir[maxn][maxn][10];
string dirmap[4]={"UP","DOWN","LEFT","RIGHT"};
int toface[5][10]={{0,2,3,4,1,5,6},{0,4,1,2,3,5,6},{0,1,6,3,5,2,4},{0,1,5,3,6,4,2}};
int dx[5]={0,0,-1,1},dy[5]={-1,1,0,0};  //0-上 1-下 2-左 3-右
int n,sx,sy,sp,tx,ty,tp;

struct state{
    int x,y,p;
};
state from[maxn][maxn][10];

void bfs(){
    memset(dist,0x3f,sizeof(dist));
    dist[sx][sy][sp]=0;

    queue<state> q;
    q.push({sx,sy,sp});
    while(q.size()){
        state curs=q.front();
        q.pop();
        int x=curs.x,y=curs.y,p=curs.p;
        if(x==tx && y==ty && p==tp) return;

        //四个方向
        for(int i=0;i<4;i++){
            int nx=x+dx[i],ny=y+dy[i],np=toface[i][p];
            if(nx<1 || nx>n || ny<1 || ny>n) continue;
            q.push({nx,ny,np});
            if(dist[x][y][p]+1<dist[nx][ny][np]){
                dist[nx][ny][np]=dist[x][y][p]+1;
                from[nx][ny][np]={x,y,p};
                dir[nx][ny][np]=i;
            }
        }
    }
}

void print_ans(int x,int y,int p){
    if(x==sx && y==sy && p==sp) return;

    print_ans(from[x][y][p].x,from[x][y][p].y,from[x][y][p].p);
    cout<<dirmap[dir[x][y][p]]<<"\n";
}

int main() {

    cout<<"Please Input the Map Size :";
    cin>>n;
    cout<<"Please Input the original position and direction: ";
    cin>>sx>>sy>>sp;
    cout<<"Please Input the Target values: ";
    cin>>tx>>ty>>tp;

    bfs();

    print_ans(tx,ty,tp);
    cout<<dist[tx][ty][tp];

    return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值