11606: 【原1606】Interesting Island
题目
题目描述
author: fangbohui 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1606
Description
在一个n*m二维网格图中,有以下三种地形:'#'代表湖泊;'.'代表陆地;'?'代表陆地与湖泊均有可能的未知地形。
求是否存在一种或多种在未知地形填充湖泊/陆地的方案,使得最后地上全部的陆地区域组成一个四联通的联通块(陆地四联通是指,在任意一个陆地格子出发,只是任意使用上下左右四个方向操作,可以访问到任何一块其他的陆地)。
无解输出“Impossible”,多解输出“Ambiguous”,唯一解则须输出一个n*m的网格图,使得之前的“?”均被填充为“#”或“.”,且陆地四联通。
Input Format
第一行两个整数n, m代表地形的行、列数。 后面一个n行m列的矩阵代表地形。
Output Format
如题意(不含引号)。
Sample Input 1
5 7
#######
#..#..#
#..?..#
#..#..#
#######
Sample Output 1
#######
#..#..#
#.....#
#..#..#
#######
Sample Input 2
5 7
#######
#...#.#
#.?.?.#
#.#...#
#######
Sample Output 2
Ambiguous
Sample Input 3
5 7
#######
#.#.#.#
#.#?#.#
#.#.#.#
#######
Sample Output 3
Impossible
Limits
- 对于30%的数据,n,m不超过2;
- 对于60%的数据,n,m不超过7;
- 对于80%的数据,n,m不超过15;
- 对于100%的数据,n,m不超过50.
BugenZhao's solution
//
// Created by BugenZhao on 2019/5/17.
//
//
// Created by BugenZhao on 2019/4/5.
//
#ifndef SBL_BQUEUE_H
#define SBL_BQUEUE_H
#include <iostream>
template<typename Item>
class BQueue {
class Node {
public:
Item item;
Node *next;
explicit Node(const Item &item, Node *next = nullptr) : item(item), next(next) {}
explicit Node(Node *next = nullptr) : next(next) {}
virtual ~Node() = default;
};
int N;
Node *first;
Node *last;
public:
BQueue() {
N = 0;
first = last = nullptr;
}
bool isEmpty() const {
return N == 0;
}
int size() const {
return N;
}
void enqueue(Item item) {
if (N == 0) {
first = new Node{item};
last = first;
} else {
Node *tmp = last;
last = new Node{item};
tmp->next = last;
}
++N;
}
Item dequeue() {
Item item = first->item;
Node *tmp = first;
first = first->next;
if (N == 1) last = nullptr;
delete tmp;
--N;
return item;
}
Item getFirst() const {
return first->item;
}
Item getLast() const {
return last->item;
}
void clear() {
Node *tmp;
while (first != nullptr) {
tmp = first;
first = first->next;
delete tmp;
}
N = 0;
first = last = nullptr;
}
virtual ~BQueue() {
Node *tmp;
while (first != nullptr) {
tmp = first;
first = first->next;
delete tmp;
}
}
private:
class Iterator {
Node *it;
Node *first;
Node *last;
public:
Iterator(Node *first, Node *last) :
it(first), first(first), last(last) {}
bool hasNext() const {
return it != nullptr;
}
Item &next() {
Node *p = it;
it = it->next;
return p->item;
}
const Item &next() const {
Node *p = it;
it = it->next;
return p->item;
}
};
public:
Iterator iterator() const {
return Iterator(first, last);
}
};
#endif //SBL_BQUEUE_H
#include <iostream>
#include <string>
using std::ios, std::cin, std::cout, std::endl, std::string;
class Point {
public:
int x, y;
Point(int x = 0, int y = 0) :
x(x), y(y) {}
};
const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};
int height[50][50];
int r, c;
BQueue<Point> q;
Point *toFill;
int toFillCount;
bool *status;
int landCount = 0;
int ansCount = 0;
int ans[50][50];
void doDfs(int x, int y, int &curCount, bool flag[50][50]) {
flag[x][y] = true;
++curCount;
for (int i = 0; i < 4; ++i) {
int xx = x + dx[i];
int yy = y + dy[i];
if (xx < 0 || xx >= r || yy < 0 || yy >= c
|| !height[xx][yy] || flag[xx][yy])
continue;
doDfs(xx, yy, curCount, flag);
}
}
int dfs(int x0, int y0) {
bool flag[50][50]{};
int curCount = 0;
doDfs(x0, y0, curCount, flag);
return curCount;
}
void DFS(int cur) {
if (ansCount >= 2) return;
if (cur == toFillCount) {
if (landCount == 0)
return;
int x0 = -1, y0 = -1;
for (int i = 0; i < r; ++i) {
for (int j = 0; j < c; ++j) {
if (x0 != -1) goto interesting;
else if (height[i][j]) x0 = i, y0 = j;
}
}
interesting:
if (dfs(x0, y0) == landCount) {
if (ansCount == 0) {
for (int i = 0; i < r; ++i) {
for (int j = 0; j < c; ++j) {
ans[i][j] = height[i][j];
}
}
}
++ansCount;
}
} else {
status[cur] = true;
height[toFill[cur].x][toFill[cur].y] = 1;
++landCount;
DFS(cur + 1);
status[cur] = false;
height[toFill[cur].x][toFill[cur].y] = 0;
--landCount;
DFS(cur + 1);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> r >> c;
int x0 = -1, y0 = -1;
if (r * c <= 150) {
char tmp;
for (int i = 0; i < r; ++i) {
for (int j = 0; j < c; ++j) {
cin >> tmp;
switch (tmp) {
case '#':
height[i][j] = 0;
break;
case '?':
height[i][j] = 1;
q.enqueue(Point(i, j));
break;
case '.':
height[i][j] = 1;
++landCount;
if (x0 == -1) x0 = i, y0 = j;
break;
}
}
}
toFillCount = q.size();
toFill = new Point[toFillCount];
status = new bool[toFillCount]{};
int ii = 0;
while (!q.isEmpty()) toFill[ii++] = q.dequeue();
DFS(0);
if (ansCount == 0)
cout << "Impossible" << endl;
else if (ansCount == 1) {
for (int i = 0; i < r; ++i) {
for (int j = 0; j < c; ++j) {
cout << (ans[i][j] ? '.' : '#');
}
cout << '\n';
}
} else
cout << "Ambiguous" << endl;
return 0;
} else {
char tmp;
for (int i = 0; i < r; ++i) {
for (int j = 0; j < c; ++j) {
cin >> tmp;
switch (tmp) {
case '#':
height[i][j] = 0;
break;
case '?':
height[i][j] = 1;
++landCount;
q.enqueue(Point(i, j));
break;
case '.':
height[i][j] = 1;
++landCount;
if (x0 == -1) x0 = i, y0 = j;
break;
}
}
}
if (landCount == 0) {
cout << "Impossible" << endl;
return 0;
}
if (x0 == -1)
x0 = q.getFirst().x, y0 = q.getLast().y;
if (dfs(x0, y0) != landCount) {
cout << "Impossible" << endl;
return 0;
} else {
bool ambiguous = false;
--landCount;
while (!ambiguous && !q.isEmpty()) {
Point point = q.dequeue();
height[point.x][point.y] = 0;
if (dfs(x0, y0) == landCount) ambiguous = true;
height[point.x][point.y] = 1;
}
if (ambiguous) {
cout << "Ambiguous" << endl;
} else {
for (int i = 0; i < r; ++i) {
for (int j = 0; j < c; ++j) {
cout << (height[i][j] ? '.' : '#');
}
cout << '\n';
}
}
}
return 0;
}
}
FineArtz's solution
/* Interesting Island */
#include <iostream>
#include <cstring>
using namespace std;
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
int n, m;
char a[55][55];
bool v[55][55], isol = true;
void floodfill(int x, int y){
v[x][y] = true;
for (int k = 0; k < 4; ++k){
int nx = x + dx[k];
int ny = y + dy[k];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny] != '#' && !v[nx][ny])
floodfill(nx, ny);
}
}
void checkfill(int x, int y){
if (a[x][y] == '.'){
isol = false;
return;
}
v[x][y] = true;
for (int k = 0; k < 4; ++k){
int nx = x + dx[k];
int ny = y + dy[k];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny] != '#' && !v[nx][ny])
checkfill(nx, ny);
if (!isol)
return;
}
}
void realfill(int x, int y){
v[x][y] = true;
a[x][y] = '#';
for (int k = 0; k < 4; ++k){
int nx = x + dx[k];
int ny = y + dy[k];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny] == '?' && !v[nx][ny])
realfill(nx, ny);
}
}
bool check(){
bool flag = true;
memset(v, 0, sizeof(v));
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
if (a[i][j] == '.'){
floodfill(i, j);
flag = false;
break;
}
}
if (!flag)
break;
}
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
if (a[i][j] == '.' && !v[i][j])
return false;
}
}
return true;
}
void checkIso(int i, int j){
isol = true;
memset(v, 0, sizeof(v));
checkfill(i, j);
if (isol){
memset(v, 0, sizeof(v));
realfill(i, j);
}
}
int main(){
bool flag = false;
int cnt = 0;
cin >> n >> m;
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
cin >> a[i][j];
if (a[i][j] == '.')
flag = true;
if (a[i][j] == '?')
++cnt;
}
}
if (!flag){
if (cnt >= 2){
cout << "Ambiguous" << endl;
return 0;
}
else if (cnt == 0){
cout << "Impossible" << endl;
return 0;
}
else{
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
if (a[i][j] == '?')
cout << '.';
else
cout << a[i][j];
}
cout << endl;
}
return 0;
}
}
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
if (a[i][j] == '?'){
checkIso(i, j);
if (a[i][j] != '?')
continue;
bool flag1 = false, flag2 = false;
a[i][j] = '.';
flag1 = check();
a[i][j] = '#';
flag2 = check();
if (flag1 && flag2){
cout << "Ambiguous" << endl;
return 0;
}
if (!flag1 && !flag2){
cout << "Impossible" << endl;
return 0;
}
a[i][j] = '.';
}
}
}
bool imp = true;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
if (a[i][j] == '.'){
imp = false;
break;
}
if (imp){
cout << "Impossible" << endl;
return 0;
}
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j)
cout << a[i][j];
cout << endl;
}
return 0;
}
ligongzzz's solution
#include "iostream"
#include "cstdio"
#include "cstring"
#include "cmath"
using namespace std;
char map_data[59][59] = { 0 };
bool visited[59][59] = { 0 };
int lx[2509] = { 0 }, ly[2509] = { 0 };
int dx[] = { 0,1,0,-1 },
dy[] = { 1,0,-1,0 };
int n, m;
int dfs(int start_x, int start_y) {
visited[start_x][start_y] = true;
int ans = 0;
if (map_data[start_x][start_y] == '.')
++ans;
for (int i = 0; i < 4; ++i) {
auto next_x = start_x + dx[i],
next_y = start_y + dy[i];
if (next_x >= 0 && next_x < n && next_y >= 0 && next_y < m &&
map_data[next_x][next_y] != '#' && !visited[next_x][next_y]) {
ans += dfs(next_x, next_y);
}
}
return ans;
}
int main() {
int land_cnt = 0, l_cnt = 0;
int start_x = 0, start_y = 0;
scanf("%d %d", &n, &m);
for (int i = 0; i < n; ++i) {
scanf("\n");
for (int j = 0; j < m; ++j) {
scanf("%c", &map_data[i][j]);
if (map_data[i][j] == '.') {
if (land_cnt == 0) {
start_x = i;
start_y = j;
}
++land_cnt;
}
else if (map_data[i][j] == '?') {
lx[l_cnt] = i;
ly[l_cnt] = j;
++l_cnt;
}
}
}
auto visited_land = dfs(start_x, start_y);
if (visited_land < land_cnt) {
printf("Impossible");
return 0;
}
for (int i = 0; i < l_cnt; ++i) {
//判断是否未访问到
if (!visited[lx[i]][ly[i]]) {
map_data[lx[i]][ly[i]] = '#';
}
}
for (int i = 0; i < l_cnt; ++i) {
if (!visited[lx[i]][ly[i]])
continue;
//修改
map_data[lx[i]][ly[i]] = '#';
memset(visited, 0, sizeof(visited));
visited_land = dfs(start_x, start_y);
if (visited_land == land_cnt) {
printf("Ambiguous");
return 0;
}
map_data[lx[i]][ly[i]] = '?';
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (map_data[i][j] == '?')
printf(".");
else
printf("%c", map_data[i][j]);
}
printf("\n");
}
return 0;
}