【 OJ 】 HDOJ1045 18年12月8日11:41 [ 39 ]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/QingCoffe/article/details/84891106

有些事情耽误了,所以最近没写代码,此题我开始的思路还算正常,后来跑偏了....开始拿到这题第一反应就是八皇后问题,递归

DFS,因为这题有X块限制,所以我的最初思路是:先和八皇后类似先在  . 块中放能放的,X块可以遮挡补充的地方先不考虑,当 . 块的最后一层放完后,开始考虑X块可以放的,一个X块可以遮挡四个方向...因此四向搜索(先前已经记录 行 列情况)X块列中看行的合法情况,行中看列的合法情况....后来发现其实这个思路是有问题的...不好实现的地方在于:

X快可以遮挡4个方向(如:【.】在【X】南可以挡住北方的子弹),假设一共有n个X快,我每次拿到一个X块(很容易一个for循环)此时有2种:第1种:我把当前的X块可以挡住的四个方向可以放的【.】全部放进去,然后取后面X块继续这么做(显然不对),第2种:我顺序检测X块四周,每当遇到一个方向能放【.】块就递归进去做下一个X块,重复上述步骤(显然也不对)

这2种情况无论怎么做都不对,因为结果很显然可以想象,假设第一个X块我挡了2个方向,第二个挡了1个,无论第一种还是第二种的循环都做不出这种情况....不可能说我第二种一路找找到最后一个X块发现没法放了,在回到第一个X快从上次检查的下一个方向继续到最后一个X块...当然X块从1到结束至多循环4次(理论上可以这么做,现实是怎么实现好烦.....)

所以开始这个思路算是壮烈牺牲了.

参考思路:https://blog.csdn.net/cr496352127/article/details/79640988

网上看了别人的思路....简洁明了干净....这题最多4层,最多16个元素,不论【.】或者【X】每个元素2种可能【放/不放】,从第1个元素搜索遍历到最后一个元素,每次遇到【.】我就检查他是否合法,如果合法我就去递归下一个元素,并且当前标记放(递归结束说明放的所有情况看完了,剩下就是当前【.】块不放的,因此递归下个元素,当前标记不放,此操作和遇到X块操作一致)

检查:

因为此题是顺序遍历元素因此元素后面的还没有放,本来X块可以挡4个方向,但是由于后面的没放,只需要在二维图中考虑左上是否有【.】即可

# include<iostream>
using namespace std;
int n,max;
char map[4][4];
bool check(int index) {
	int x, y;
	x = index / n; y = index%n;
	for (int i = x-1; i >= 0; i--) {
		if (map[i][y] == 'X')break;
		if (map[i][y] == 'V')return false;
	}//列检查
	for (int j = y-1; y >= 0; y--) {
		if (map[x][j] == 'X')break;
		if (map[x][j] == 'V')return false;
	}//行检查
	return true;
}
void DFS(int index,int num) {
	if (index == n*n) {
		if(num>max)
			max = num;
		return;
	}
	int x, y;
	x = index / n; y = index%n;
	if (map[x][y] == '.'&&check(index)) {
		map[x][y] = 'V';//标记为访问
		DFS(index + 1, num + 1);
		map[x][y] = '.';
	}
	DFS(index + 1, num);
}
int main(void) {
	int i, j;
	cin >> n;
	while (n) {
		max = 0;
		for (i = 0; i < n; i++)
			for (j = 0; j < n; j++)
				cin >> map[i][j];//录入地图
		DFS(0, 0);
		cout << max << endl;
		cin >> n;
	}
	system ("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/QingCoffe/article/details/84891106