BZOJ 1054 广搜

1054: [HAOI2008]移动玩具

  在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动
时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移动次数将初始的玩具状态移
动到某人心中的目标状态。

Input

  前4行表示玩具的初始状态,每行4个数字1或0,1表示方格中放置了玩具,0表示没有放置玩具。接着是一个空
行。接下来4行表示玩具的目标状态,每行4个数字1或0,意义同上。

Output

  一个整数,所需要的最少移动次数。

Sample Input

1111
0000
1110
0010

1010
0101
1010
0101

Sample Output

4
 

分析:

这道题拿到之后第一件想到的事情就是,诶!这是道深搜题诶。而且这个搜索很明显。这道题的数据应该也挺水的所以,就没想什么别的方法

我想的简单粗暴。
1,我们发现,无论怎么移动,如果初始和最终都放了话,那个位置其实不用考虑。因为。就算要移动它,因为它本来就要放哪个位置,那就得找一个新的放在哪个位置。这个过程我们可以想成移动别的点经过了这个位置。
2,因为如果深搜每次只能移动一个点。那么我们就在去完重后对每个初始节点将整张图搜索一遍。将每个遇到对目标节点记录其的步数。这些都放到一个forces [ number ] [ z ] 这里number指的是第几个初始节点 z指的是第几个目标节点。枚举整个图。完成整个表。。为什么我们每次不举最短的那个目标节点。因为。纵观全局,可能会遇到。虽然这个点当前是最近的。但是对别的点来说就没有最近的点。所以我们得考虑全局。当然考虑全局有很多办法。但是我都说了没想什么办法。直接暴力。
3,之后就是组合整个forces数组了,每次每个目标节点只能与一个初始节点匹配。同时还保证综合的步数最小。因为我没这么想(同上)。既然都这么暴力了!那就更暴力一点啊啊啊啊!!!!!!直接用全排列来解决这个问题。

这就是我的黄暴做法。然而所以。就是这样。dalao看到了千万别喷。

#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
int one[5][5],two[5][5],cnt;
int forces[17][17];
int left[4]={1,-1,0,0},right[4]={0,0,1,-1};
int visit[5][5],ans=214748;
int visit_1[20];
struct node{
    int x,y,step;
}queue[1001];
void BFS(int x_1,int y_1,int number)
{
    memset(visit,0,sizeof(visit));
    int head=1,last=1;
    node first;
    first.x=x_1;first.y=y_1;first.step=0;
    queue[1]=first;visit[x_1][y_1]=1;
    while(head<=last)
    {
	node news=queue[head];
	for(int i=0;i<4;++i)
	{
	    int x=news.x+left[i],y=news.y+right[i];
	    if(x>0&&x<=4&&y>0&&y<=4&&(!visit[x][y]))
	    {
		node zz;
		zz.x=x;zz.y=y;zz.step=news.step+1;
		if(two[x][y]){
		    forces[number][two[x][y]]=zz.step;
		}
		queue[++last]=zz;
		visit[x][y]=1;
	    }
	}
	++head;
    }
    return ;
}
int lie[20];
void DFS(int x)
{
    if(x>cnt)
    {
	int ans_1=0;
	for(int i=1;i<=cnt;++i)
	{
	    ans_1+=forces[i][lie[i]];
	}
	ans=min(ans,ans_1);
	return ;
    }
    for(int i=1;i<=cnt;i++)
    {
	if(visit_1[i])continue;
	visit_1[i]=1;
	lie[x]=i;
	DFS(x+1);
	visit_1[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&&two[i][j]==one[i][j])
		one[i][j]=two[i][j]=0;
	    else if(two[i][j]==1){
	    	++cnt;
	    	two[i][j]=cnt;
	    }
	}
     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);
	     }
	 }
     DFS(1);
     printf("%d",ans);
     return 0;
}

嗯。就是这样。我觉得已经够暴力了。。

原文地址:https://www.cnblogs.com/uncle-lu/p/5958517.html