uva - 639 - Don't Get Rooked

来源:互联网 发布:淘宝代画效果图被骗 编辑:程序博客网 时间:2024/05/22 04:53

类型:

暴力求解中的回溯法。

题目要求:

给你一个n,1-4,代表一个n*n的棋盘,然后输入这个棋盘,‘.’表示这个位置可以放置城堡,‘X’表示这个位置有城墙。放在在同一行或列的城堡会相互进攻,除非他们之间有城墙。
你的任务就是输入一个棋盘,输出这个棋盘上最多可以同时存在几个城堡。


解题思路:

用回溯法去枚举,vis数组中0表示可以放置城堡,1表示这个位置有城堡,2表示这个位置有城墙。然后不断回溯枚举去判断。注意,回溯进去到下一层改了vis数组后,回来的时候要改回来。


细节注意:

1、改了vis数组要改回来;
2、新放置一个城堡时,判断是否和前边的冲突。要判断那个位置的前后所有位置是否冲突。刚开始只判断了前边,以为城堡就是按顺序放的,但是别忘了。例如 0100,这种,下一次判断0,0位置,要考虑0,1位置。

AC代码:


#define Local#include <iostream>#include <iomanip>#include <string>#include <cstring>#include <cstdio>#include <queue>#include <stack>#include <algorithm>#include <cmath>using namespace std;char chess[5][5];int vis[5][5], _max, n;//记录城堡,0代表可以放,1代表有城堡了,2代表有城墙。int judge(int a, int b)//参数不能是n,n为全局的。{int i = 0, j = 0, flag = 1;for (i = 0; i < n; i++){if (i != a)if (1 == vis[i][b])//这一列上有别的城堡{flag = 0;if (i <= a)for (j = i+1; j <= a; j++){if (2 == vis[j][b])//两个城堡之间有城墙flag = 1;}elsefor (j = a+1; j <= i; j++){if (2 == vis[j][b])//两个城堡之间有城墙flag = 1;}}}if (!flag)return 0;for (i = 0; i < n; i++){if (i != b)if (1 == vis[a][i]){flag = 0;if (i <= b)for (j = i+1; j <= b; j++){if (2 == vis[a][j])flag = 1;}elsefor (j = b+1; j <= i; j++){if (2 == vis[a][j])flag = 1;}}}return flag;}void DFS (int cur){int i = 0, j = 0;if (cur > _max)_max = cur;for(i = 0; i < n; i++){for (j = 0; j < n; j++){if (!vis[i][j])//这个位置可以安放城堡{if (judge(i, j))// 比较这个位置是否可行,可行就安上{vis[i][j] = 1;DFS(cur+1);vis[i][j] = 0;}}}}}int main(){#ifdef Localfreopen("a.in", "r", stdin);//freopen("a.out", "w", stdout);#endifint i = 0, j = 0;while (cin >> n && n){_max = 0;memset(vis, 0, sizeof(vis));memset(chess, '\0', sizeof(chess)); for (i = 0; i < n; i++){for (j = 0; j < n; j++){cin >> chess[i][j];if ('X' == chess[i][j])vis[i][j] = 2;//2代表是城墙}}//输入数据DFS(0);cout << _max << endl;}}


0 0
原创粉丝点击