第1部分 基础算法(提高篇)--第4章 广搜的优化技巧1453:移动玩具

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 ;
}
展开阅读全文
©️2020 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值