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
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; }
嗯。就是这样。我觉得已经够暴力了。。