移动玩具(DFS、BFS)

题目:
移动玩具洛谷题目

解题思路:

先利用bfs找出每一个起始玩具,到所有终点玩具所需移动步长求出。存放到dis数组中
在利用dfs和"全排列"思想类似,一个萝卜一个坑,找出所有搭配情况。

不懂全排列dfs做法的同学点超链接
全排列

细枝末节:

需要将起始玩具和终点的玩具位置进行编号。
如果起始玩具和终点玩具位置相同我们可以直接抹掉,不用考虑!

代码实现:(里面全是细节~~~)

#include <bits/stdc++.h>
using namespace std;
int one[5][5],two[5][5];//存放玩具位置
int x_mov[4]= {1,-1,0,0}; //移动方向表示
int y_mov[4]= {0,0,1,-1};
int visit_B[5][5];//BFS所用的visit
int visit_D[20];//DFS所用的visit
int dis[20][20];//x存放起始玩具编号,y存放终点位置编号,dis内容存放这个起点到这个终点的距离
int cnt,ans=0x7f7f7f7f;
struct node
{
    int x,y,step;//存放one中玩具坐标,以需要步长(步长不懂往下看)
};
queue<node> q;//bfs用队列实现


void bfs(int x,int y,int number)
{
    node first;
    memset(visit_B,0,sizeof(visit_B));
    first.x=x,first.y=y,first.step=0;
    visit_B[x][y]=1;
    q.push(first);
    while(!q.empty())
    {
        node t=q.front();
        q.pop();
        //枚举状态
        for(int i=0; i<4; i++)
        {
            int nx=t.x+x_mov[i];//new x
            int ny=t.y+y_mov[i];//new y
            node tt;
            if(nx>=1&&nx<=4&&ny>=1&&ny<=4&&!visit_B[nx][ny])
            {
                visit_B[nx][ny]=1;
                tt.x=nx;
                tt.y=ny;
                tt.step=t.step+1;//走一步
                q.push(tt);
                if(two[nx][ny])//终点在(nx,ny)有玩具
                {
                    //将一共多少步存到dis数组里
                    dis[number][two[nx][ny]]=tt.step;
                }
            }
        }
    }
}
int lie[20];//存放终点玩具编号
void dfs(int x)
{
    if(x>cnt)//枚举到终点情况
    {
        int sum=0;
        //求出这条路径的总步长
        for(int i=1; i<=cnt; i++)
        {
            sum+=dis[i][lie[i]];
        }
        ans=min(ans,sum);
        return ;
    }
    for(int i=1; i<=cnt; i++)
    {
        if(!visit_D[i])//没被标记
        {
            visit_D[i]=1;
            lie[x]=i;//第x个起点玩具对应的终点玩具为i
            dfs(x+1);//枚举第x+1个起点玩具
            visit_D[i]=0;//取消标记
            lie[x]=0;//取消标记
        }
    }
    return;
}


int main()
{

    for(int i=1; i<=4; i++)
    {
        for(int j=1; j<=4; j++)
        {
            scanf("%1d",&one[i][j]);//起点玩具先不必编号,后面要消去重复位置
        }
    }
    for(int i=1; i<=4; i++)
    {
        for(int j=1; j<=4; j++)
        {
            scanf("%1d",&two[i][j]);
            if(two[i][j]==1&&one[i][j]==1)
            {
                //消去起始和终点相同的玩具
                two[i][j]=0;
                one[i][j]=0;
            }
            else if(two[i][j]==1)
            {
                //编号,终点玩具
                cnt++;
                two[i][j]=cnt;
            }
        }
    }
    //利用bfs找出每个起始位置的玩具,到终止位置的玩具的距离
    int cnt_1=0;
    for(int i=1; i<=4; i++)
    {
        for(int j=1; j<=4; j++)
        {
            if(one[i][j])
            {
                cnt_1++;
                bfs(i,j,cnt_1);//传入位置信息,以及编号:cnt_1
            }
        }
    }

    dfs(1);//从编号为1的起始位置开始枚举状态
    printf("%d",ans);
    return 0;
}

多多点赞支持!写写大家。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值