题目链接:http://poj.org/problem?id=2585 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2193
题目大意:
有9个窗口,每个窗口占4个格子,并且每个窗口的位置是固定的。如果重叠的话,在前面的窗口会覆盖另一种窗口,这9个窗口在4*4的矩阵里面,给出一种矩阵的格局。问这中格局是不是合法的。
题目思路:
还是看的书上的。刚开始一点也没有思路。方法就是:16个格子,每个格子可能会存在哪几种窗口,这是可以枚举出来的。针对输入的矩阵,那么可以判断,每一个格子会覆盖哪几种窗口,如果这种窗口在16个格子里面出现过,那么就可以判断当前这个格子一定覆盖了它,那么就可以用一条有向边连接当前窗口和被覆盖的窗口。这样,就可以得到一个图。在16个格子里面没有出现过的窗口我们可以不考虑。得到有向图后,发现,如果存在一个有向环,那么就一定是不合理的,因为这表明,一种窗口A覆盖了另一种窗口B,同时B又覆盖了A,这是不可能的。所以这个矩阵就是不合法的。反之,如果不存在有向环,就是合法的。这样,就转化为用拓扑排序判断环的问题了。先建图,再判断环。
写了两遍,其中出现各种BUG……
第一遍:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cctype> 6 #include <stack> 7 #include <queue> 8 #include <map> 9 #include <set> 10 #include <vector> 11 #include <cmath> 12 #include <algorithm> 13 #define lson l, m, rt<<1 14 #define rson m+1, r, rt<<1|1 15 using namespace std; 16 typedef long long int LL; 17 const int MAXN = 0x3f3f3f3f; 18 const int MIN = -0x3f3f3f3f; 19 const double eps = 1e-9; 20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1}, 21 {1,1},{1,-1},{-1,-1}}; 22 string cover[4][4]; 23 int a[10][10];bool g[10][10];int id[10]; 24 map<int, bool>mymap; 25 26 int main(void){ 27 #ifndef ONLINE_JUDGE 28 freopen("poj2585.in", "r", stdin); 29 #endif 30 int i, j, k; 31 for (i = 0; i < 4; ++i) for (j = 0; j < 4; ++j) 32 cover[i][j].erase(); 33 for (k = 1; k <= 9; ++k) { 34 i = (k - 1) / 3; j = (k - 1) % 3; 35 cover[i][j] += (k + '0'); 36 cover[i][j+1] += (k + '0'); 37 cover[i+1][j] += (k + '0'); 38 cover[i+1][j+1] += (k + '0'); 39 } 40 string s; int t = 0; 41 while (cin >> s) { 42 mymap.clear(); 43 for (i = 0; i < 10; ++i) 44 { 45 id[i] = 0; 46 for (j= 0; j < 10; ++j) 47 { 48 g[i][j] = false; a[i][j] = 0; 49 } 50 } t = 0; 51 if (s == "ENDOFINPUT") break; 52 for (i = 0; i < 4; ++i) { 53 for (j = 0; j < 4; ++j) { 54 scanf("%d", &k); a[i][j] = k; 55 if (mymap[k] == false) { mymap[k] = true; t++; } 56 } 57 } 58 for (i = 0; i < 4; ++i) { 59 for (j = 0; j < 4; ++j) { 60 for (int p = 0; p < cover[i][j].length(); ++p) { 61 if (g[a[i][j]][cover[i][j][p] -'0'] == false && a[i][j]!=cover[i][j][p] -'0' && mymap[cover[i][j][p]-'0'] ) { 62 g[a[i][j]][cover[i][j][p] -'0'] = true; id[cover[i][j][p]-'0' ]++; 63 } 64 } 65 } 66 } 67 bool flag = true; 68 for (i = 0; i < t; ++i) { 69 k = 1; 70 while (!(mymap[k]&&id[k]==0) && (k <= 9)) k++; 71 if (k > 9) {flag = false; break; } 72 mymap[k] = false; 73 for (j = 1; j <= 9; ++j) { 74 if (g[k][j] == true && mymap[j] ) id[j]--; 75 } 76 } 77 if (flag) cout << "THESE WINDOWS ARE CLEAN" << endl; 78 else cout << "THESE WINDOWS ARE BROKEN" << endl; 79 cin >> s; 80 } 81 82 return 0; 83 }
第二遍:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cctype> 6 #include <stack> 7 #include <queue> 8 #include <map> 9 #include <set> 10 #include <vector> 11 #include <cmath> 12 #include <algorithm> 13 #define lson l, m, rt<<1 14 #define rson m+1, r, rt<<1|1 15 using namespace std; 16 typedef long long int LL; 17 const int MAXN = 0x3f3f3f3f; 18 const int MIN = -0x3f3f3f3f; 19 const double eps = 1e-9; 20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1}, 21 {1,1},{1,-1},{-1,-1}}; 22 string cover[4][4] = { "1", "12", "23", "3", "14", "1245", "2356", "36", 23 "47", "4578", "5689", "69", "7", "78", "89", "9"}; 24 bool edge[10][10]; 25 int a[10][10]; 26 map<int, bool>mymap; 27 int mystack[10], Count[10]; 28 int main(void){ 29 #ifndef ONLINE_JUDGE 30 freopen("poj2585.in", "r", stdin); 31 #endif 32 string s; int i, j, k; 33 while (cin >> s) { 34 if (s == "ENDOFINPUT") break; 35 mymap.clear(); memset(edge, false, sizeof(edge)); 36 int kind = 0; 37 for (i = 0; i < 10; ++i) { 38 Count[i] = mystack[i] = 0; 39 } 40 for (i = 0; i < 4; ++i) { 41 for (j = 0; j < 4; ++j) { 42 scanf("%d", &a[i][j]); 43 if (!mymap[a[i][j] ]) { 44 mymap[a[i][j] ] = true; kind++; 45 } 46 } 47 } 48 for (i = 0; i < 4; ++i) { 49 for (j = 0; j < 4; ++j) { 50 for (int p = 0; p < cover[i][j].length(); ++p) { 51 int nu = cover[i][j][p] - '0'; 52 if (mymap[nu] && edge[a[i][j] ][nu ]==false && nu != a[i][j] ) { 53 edge[a[i][j] ][nu] = true; Count[nu]++; 54 } 55 } 56 } 57 } 58 int top = 0, cnt = 0; 59 for (i = 1; i <= 9; ++i) { 60 if (Count[i] == 0 && mymap[i]) mystack[++top] = i; 61 } 62 while (top != 0) { 63 int fo = mystack[top]; Count[fo] = -1; 64 top--; cnt++; 65 for (i = 1; i <= 9; ++i) { 66 if (edge[fo][i] == true && mymap[i]) { 67 Count[i]--; 68 } 69 } 70 if (!top) // 这个地方,调试很久。不能重复入栈!也就是说,除非栈空了,否则,不要扫描。 71 for (i = 1; i <= 9; ++i) { 72 if (Count[i] == 0 && mymap[i]) mystack[++top] = i; 73 } 74 } 75 if (cnt < kind) cout << "THESE WINDOWS ARE BROKEN\n"; 76 else cout << "THESE WINDOWS ARE CLEAN\n"; 77 cin >> s; 78 } 79 80 return 0; 81 }
细节,很重要。还有,书上的代码貌似有错误……