USACO 2.1.1 The Castle
IOI经典原题
题意:一幅城堡中的各个房间,东西南北四个方向都可能会有,没有墙的话视为连通,
求解有多少个连通分量,最大房间的大小是多少,同时,如果移除一个墙,最大的房间面积是多少,
移除墙的位置在哪儿。注意,移除墙的顺序为自南往北,先北面的墙再东面的墙(题意理解上比较麻烦的地方)
2.1的TEXT中讲到了flood fill算法,结合DFS和BFS的基本搜索方法
对于本题,先DFS求出所有的连通分量,
然后按照题目的要求,顺序搜索移除的墙的位置,得到最优解(官方的解题思路类似)
提交了3次。。
/* ID: lsswxr1 PROG: castle LANG: C++ */ #include <iostream> #include <vector> #include <map> #include <list> #include <set> #include <deque> #include <stack> #include <queue> #include <algorithm> #include <cmath> #include <cctype> #include <cstdio> #include <iomanip> #include <cmath> #include <cstdio> #include <string> #include <cstring> #include <fstream> using namespace std; #define USACO #ifdef USACO #define cin fin #define cout fout #endif ////////////////////////////////////////////////////////////////////////// ///宏定义 const int INF = 1000000000; const int MAXN = 50; const int maxn = MAXN; ///全局变量 和 函数 int M, N; struct node { int component; int wall; }; node Nodes[maxn][maxn]; int maxRoom; int comp; bool vis[maxn][maxn]; int compSize[maxn * maxn]; void dfs(int curRow, int curCol) { vis[curRow][curCol] = true; Nodes[curRow][curCol].component = comp; compSize[comp]++; //向西搜索 if (curCol > 0) { if ((Nodes[curRow][curCol].wall & 0x1) != 0x1) { if (!vis[curRow][curCol - 1]) dfs(curRow, curCol - 1); } } //向北搜索 if (curRow > 0) { if ((Nodes[curRow][curCol].wall & 0x2) != 0x2) { if(!vis[curRow - 1][curCol]) dfs(curRow - 1, curCol); } } //向南搜索 if (curRow < N - 1) { if ((Nodes[curRow][curCol].wall & 0x8) != 0x8) { if (!vis[curRow + 1][curCol]) dfs(curRow + 1, curCol); } } //向东搜索 if (curCol < M - 1) { if ((Nodes[curRow][curCol].wall & 0x4) != 0x4) { if (!vis[curRow][curCol + 1]) { dfs(curRow, curCol + 1); } } } } int maxRemoveSize; int maxRemoveRow, maxRemoveCol; char maxRemoveDir; int main() { #ifdef USACO ofstream fout ("castle.out"); ifstream fin ("castle.in"); #endif while (cin >> M >> N) { memset(Nodes, 0, sizeof(Nodes)); memset(vis, false, sizeof(vis)); memset(compSize, 0, sizeof(compSize)); maxRoom = -INF; maxRemoveSize = -INF; comp = 1; for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { int curWall; cin >> curWall; Nodes[i][j].wall = curWall; } } for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { if (!vis[i][j]) { dfs(i, j); comp++; } } } for (int i = 0; i < comp; i++) maxRoom = max(maxRoom, compSize[i]); maxRemoveSize = maxRoom; for (int j = 0; j < M; j++) { for (int i = N - 1; i >= 0; i--) //少写了一个等号.. { //移除北面的墙 if ((i > 0) && ((Nodes[i][j].wall & 0x2) == 0x2)) { if ((Nodes[i][j].component != Nodes[i - 1][j].component) && (compSize[Nodes[i][j].component] + compSize[Nodes[i - 1][j].component] > maxRemoveSize)) { maxRemoveSize = compSize[Nodes[i][j].component] + compSize[Nodes[i - 1][j].component]; //写错了第一个式子 maxRemoveDir = 'N'; maxRemoveRow = i; maxRemoveCol = j; } } //移除东面的墙 if ((j < M - 1) && ((Nodes[i][j].wall & 0x4) == 0x4)) { if ((Nodes[i][j].component != Nodes[i][j + 1].component) && (compSize[Nodes[i][j].component] + compSize[Nodes[i][j + 1].component] > maxRemoveSize)) { maxRemoveSize = compSize[Nodes[i][j].component] + compSize[Nodes[i][j + 1].component]; maxRemoveDir = 'E'; maxRemoveRow = i; maxRemoveCol = j; } } } } cout << comp - 1 << endl; cout << maxRoom << endl; cout << maxRemoveSize << endl; cout << maxRemoveRow + 1 << " " << maxRemoveCol + 1 << " " << maxRemoveDir << endl; } ///结束 return 0; }