题目:
移动玩具洛谷题目
解题思路:
先利用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;
}
多多点赞支持!写写大家。