poj2585&&zoj2193 Window Pains ——拓扑排序入门题

题目链接: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 }

细节,很重要。还有,书上的代码貌似有错误……

posted on 2013-04-30 19:15  aries__liu  阅读(755)  评论(0编辑  收藏  举报