题意:有n*m的房间,'.'表示可以被点亮,'#'表示不能被点亮,每点亮一个房间会使旁边的房间也点亮,有意盏特别的灯可以选择周围不同方向的房间点亮。问最少需要多少灯使得所有房间点亮
分析:需要被点亮的房间最多只有15个,所以考虑状压,然后暴力枚举选择哪一个当作特殊灯和枚举选择哪个方向使旁边的房间亮,注意清空vis数组需要优化,memset超时。上交6分钟1Y,Orz。。。额,看错榜了,最快的19分钟,而且这不是第一道水题,汗
/************************************************ * Author :Running_Time * Created Time :2015/10/22 星期四 18:25:25 * File Name :A.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 2e2 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const double EPS = 1e-8; char room[N][N]; struct Point { int x, y; Point (int x, int y) : x (x), y (y) {} }; int n, m; bool vis[N][N]; void back_nomal(int x, int y) { vis[x][y] = false; if (x - 1 >= 1) vis[x-1][y] = false; if (y + 1 <= m) vis[x][y+1] = false; } void back_special(int x, int y, int type) { if (type == 1) { back_nomal (x, y); return ; } else if (type == 2) { if (x + 1 <= n) { vis[x+1][y] = false; } if (y + 1 <= m) { vis[x][y+1] = false; } } else if (type == 3) { if (x + 1 <= n) { vis[x+1][y] = false; } if (y - 1 >= 1) { vis[x][y-1] = false; } } else if (type == 4) { if (x - 1 >= 1) { vis[x-1][y] = false; } if (y - 1 >= 1) { vis[x][y-1] = false; } } vis[x][y] = false; } bool light_nomal(int x, int y) { if (x - 1 >= 1 && room[x-1][y] != '.') return false; if (y + 1 <= m && room[x][y+1] != '.') return false; if (x - 1 >= 1) { vis[x-1][y] = true; } if (y + 1 <= m) { vis[x][y+1] = true; } vis[x][y] = true; return true; } bool light_special(int x, int y, int type) { if (type == 1) { return light_nomal (x, y); } else if (type == 2) { if (x + 1 <= n && room[x+1][y] != '.') return false; if (y + 1 <= m && room[x][y+1] != '.') return false; if (x + 1 <= n) { vis[x+1][y] = true; } if (y + 1 <= m) { vis[x][y+1] = true; } } else if (type == 3) { if (x + 1 <= n && room[x+1][y] != '.') return false; if (y - 1 >= 1 && room[x][y-1] != '.') return false; if (x + 1 <= n) { vis[x+1][y] = true; } if (y - 1 >= 1) { vis[x][y-1] = true; } } else if (type == 4) { if (x - 1 >= 1 && room[x-1][y] != '.') return false; if (y - 1 >= 1 && room[x][y-1] != '.') return false; if (x - 1 >= 1) { vis[x-1][y] = true; } if (y - 1 >= 1) { vis[x][y-1] = true; } } vis[x][y] = true; return true; } int main(void) { while (scanf ("%d%d", &n, &m) == 2) { if (!n && !m) break; for (int i=1; i<=n; ++i) { scanf ("%s", room[i] + 1); } int cnt = 0; memset (vis, false, sizeof (vis)); vector<Point> V; for (int i=1; i<=n; ++i) { for (int j=1; j<=m; ++j) { if (room[i][j] == '.') { cnt++; V.push_back (Point (i, j)); } } } if (cnt == 0) { puts ("0"); continue; } int tot = 1 << cnt; int ans = INF; for (int i=0; i<tot; ++i) { for (int k=0; k<cnt; ++k) { for (int l=1; l<=4; ++l) { bool ok = true; for (int j=0; j<cnt; ++j) { if (i & (1 << j)) { if (j == k) { if (!light_special (V[j].x, V[j].y, l)) { ok = false; break; } } else { if (!light_nomal (V[j].x, V[j].y)) { ok = false; break; } } } } if (!ok) { for (int j=0; j<cnt; ++j) { if (j == k) back_special (V[j].x, V[j].y, l); else back_nomal (V[j].x, V[j].y); } continue; } bool flag = true; for (int j=0; j<cnt; ++j) { int x = V[j].x, y = V[j].y; if (!vis[x][y]) { flag = false; break; } } if (flag) { ans = min (ans, __builtin_popcount (i)); } for (int j=0; j<cnt; ++j) { if (j == k) back_special (V[j].x, V[j].y, l); else back_nomal (V[j].x, V[j].y); } } } } printf ("%d ", ans == INF ? -1 : ans); } return 0; }