1453:移動玩具
時間限制: 1000 ms 內存限制: 65536 KB
提交數: 296 通過數: 172
【題目描述】
原題來自:HAOI 2008
在一個 4×4 的方框內擺放了若干個相同的玩具,某人想將這些玩具重新擺放成爲他心中理想的狀態,規定移動時只能將玩具向上下左右四個方向移動,並且移動的位置不能有玩具,請你用最少的移動次數將初始的玩具狀態移動到目標狀態。
【輸入】
前四行表示玩具的初始狀態,每行 4 個數字 1 或 0,1 表示方格中放置了玩具,0 表示沒有放置玩具。
接着是一個空行。
接下來四行表示玩具的目標狀態,每行 4 個數字 1 或 0,意義同上。
【輸出】
一個整數,所需要的最少移動次數。
【輸入樣例】
1111
0000
1110
0010
1010
0101
1010
0101
【輸出樣例】
4
思路:深搜暴力求解,對於已經匹配好的點,我們直接把他賦值爲0;這個點去匹配其他點,肯定不如直接用這個點已匹配的點更優。如果另一個點的某條轉移路徑需要路過這個點,我們可以轉換爲:把這個點先轉移到目標點,然後再把另一個點轉移過來。 我們只需要求得未匹配點到未匹配目標點的最短距離即可。 這個用數學方式:兩點x座標差的絕對值+兩點y座標的絕對值,即 abs(x1 - x2)+ abs(y1 - y2)。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
struct node {
int x,y;
} c[26] ;//記錄每一個a[][]有玩具的位置
int a[5][5],b[5][5],w[5][5][5][5] ;
bool d[5][5];
int _sum = 0,_min = INF ;//_sum記錄 a[][] == 1 的個數, _min 是最小值 (答案)
void BFS ( int tot , int ans ) {//tot 是尋找到的個數 , ans 是需要步數
if ( tot > _sum ) { //當搜索個數 > 原本個數時,跳出
_min = min ( _min , ans ) ; // 統計答案
return ;
}
for ( int i = 1 ; i <= 4 ; i ++ ) {
for ( int j = 1 ; j <= 4 ; j ++ ) {
if ( w[c[tot].x][c[tot].y][i][j] != 0 && d[i][j] == 0) {
d[i][j] = 1 ;
BFS ( tot + 1 , ans + w[c[tot].x][c[tot].y][i][j] ) ; //進入更深一層的遞歸
d[i][j] = 0 ; //回溯
}
}
}//查找
}
int main() {
char ch ;//用字符更好輸入
for ( int i = 1 ; i <= 4 ; i ++ ) {
for ( int j = 1 ; j <= 4 ; j ++ ) {
cin >> ch;
a[i][j] = ch - '0' ;
}
}//輸入
for ( int i = 1 ; i <= 4 ; i ++ ) {
for ( int j = 1 ; j <= 4 ; j ++ ) {
cin >> ch ;
b[i][j] = ch - '0' ;
if ( a[i][j] == b[i][j] ) a[i][j] = b[i][j] = 0 ;
}
}//輸入
for (int i = 1 ; i <= 4 ; i ++ ) {
for (int j = 1 ; j <= 4 ; j ++ ) {
if (a[i][j] == 1) {
c[++ _sum].x = i;
c[_sum].y = j ;
for (int k = 1; k <= 4; k ++) {
for (int x = 1 ; x <= 4; x ++) {
if (b[k][x] == 1) w[i][j][k][x] = abs(i - k) + abs(j - x) ;
}
}
}
}
}//w[][][][]儲存(i,j) --> (k,x) 的距離
BFS(1,0);//BFS搜索
printf("%d",_min);//輸出
return 0 ;
}