POJ 1099 -- Square Ice
字符处理题.根据所给 ASM 数据决定水分子的化学键形成方式. 这道题目乍一看不知道某一水分子周围的其他水分子的成键情况,差点冲动,一阵爆搜.
仔细分析数据规模以及样例数据之后发现:ASM 为1或-1的水分子就是 Square Ice 的骨架,只要它们确定了,其他的水分子的成键就可以确定了.
一个水分子以一个 oxygen atom 为中心,定能且只能与两个 hydrogen atom 成键,搭建好 ASM = 1, -1的水分子后,我的 第一思路 是:不妨设当前的需要成键的氧原子坐标为 O0 ( h0 , w0 ),设置增量集合为 D { ( Δh , Δd ) | (-2, 0), (2, 0), (0, -2), (0, 2) },则待成键的四个 hydrogen atoms 的坐标就可以计算出来,即 O1 ( h0 + Δh , w0 + Δd ).
由于成键数量为2,我只要定义一个 cnt = 0,当 verify_atom 并发现一个“可以用的” hydrogen atom,就++cnt,直到cnt = 2成立. 接着想想 verify_atom 这个函数应该怎么写?首先找到一个 hydrogen atom 的坐标,然后 verify: 上下是否有 ‘|’,左右是否有 ‘-’. 这样想想挺好,写完之后发现有问题,具体的错在什么地方留给大家思考. 所以对于 ASM = 0 的 atom,我发现它的成键方式只有四种,简言之就是:“上左”、“上右”、“下左”、“下右”,接下来枚举就行了,一旦成键成功马上调到下一个 atom,大功告成.
题目很水,但是思路要很清晰,其中 draw_h2o 函数用了迭代开发的风格,我会在以后的文章中说说对于这种开发模式的心得. 最后给出代码.
1
/*
http://poj.org/problem?id=1099
*/
2
3 #include <iostream>
4 #include <cstring>
5
6 using namespace std;
7
8 const int Mmx = 13, Max = 1 << 7;
9
10 inline bool verify_atom( char h2o[Max][Max], int atom_y, int atom_x, int height, int width)
11 {
12 const int dy[] = { -1, 0, 1, 0 }, dx[] = { 0, 1, 0, -1 };
13 for ( int d = 0; d < 4; ++d)
14 {
15 int ny = atom_y + dy[d], nx = atom_x + dx[d];
16 if (nx <= 0 && nx >= width - 1 && ny < 0 && ny >= height - 1)
17 continue;
18 if (h2o[ny][nx] == '|' || h2o[ny][nx] == '-')
19 return false;
20 }
21 return true;
22 }
23
24 inline void draw_h2o( int asmx[Mmx][Mmx], char h2o[Max][Max], int m)
25 {
26 const int width = 2 * m + 1 + 2 * m + 2, height = 4 * m - 1;
27
28 for ( int w = 0; w < width; ++w)
29 h2o[0][w] = h2o[height - 1][w] = '*';
30 for ( int h = 1; h < height - 1; ++h)
31 {
32 for ( int w = 0; w < width; ++w)
33 {
34 if (w == 0 || w == width - 1)
35 h2o[h][w] = '*';
36 else
37 h2o[h][w] = ' ';
38 }
39 } // end: init h2o array
40
41 for ( int h = 1; h < height - 1; h += 4)
42 {
43 for ( int w = 1; w < width - 1; w += 4)
44 h2o[h][w] = 'H';
45 for ( int w = 3; w < width - 1; w += 4)
46 h2o[h][w] = 'O';
47 } // end: draw 'h'-and-'o' line
48
49 for ( int h = 3; h < height - 1; h += 4)
50 {
51 for ( int w = 3; w < width - 1; w += 4)
52 h2o[h][w] = 'H';
53 } // end: draw only-'h' line
54
55 for ( int h = 1; h <= m; ++h)
56 {
57 for ( int w = 1; w <= m; ++w)
58 {
59 int oxygen_h = 1 + 4 * (h - 1), oxygen_w = 3 + 4 * (w - 1);
60 if (asmx[h][w] == 1)
61 h2o[oxygen_h][oxygen_w - 1] = h2o[oxygen_h][oxygen_w + 1] = '-';
62 if (asmx[h][w] == -1)
63 h2o[oxygen_h - 1][oxygen_w] = h2o[oxygen_h + 1][oxygen_w] = '|';
64 } // end: draw h2o whose asmx equals 1 or -1
65 }
66
67 for ( int h = 1; h <= m; ++h)
68 {
69 for ( int w = 1; w <= m; ++w) if (asmx[h][w] == 0)
70 {
71 int oxygen_h = 1 + 4 * (h - 1), oxygen_w = 3 + 4 * (w - 1);
72 const int dh[] = { -1, -1, 1, 1 }, dx[] = { -1, 1, -1, 1 };
73 // up-left up-right down-left down-right
74 for ( int d = 0; d < 4; ++d)
75 {
76 int y1 = oxygen_h + dh[d], x1 = oxygen_w, y2 = oxygen_h, x2 = oxygen_w + dx[d];
77 if (y1 <= 0 || y1 >= height - 1 || x1 <= 0 || x1 >= width - 1 || y2 <= 0 || y2 >= height - 1 || x2 <= 0 || x2 >= width - 1)
78 continue;
79 if (verify_atom(h2o, y1 + dh[d], x1, height, width) && verify_atom(h2o, y2, x2 + dx[d], height, width))
80 {
81 h2o[y1][x1] = '|';
82 h2o[y2][x2] = '-';
83 break;
84 }
85 }
86 }
87 } // end: draw orthogonal h2o molecules (asmx = 0)
88 }
89
90 inline void print_h2o( char h2o[Max][Max], int m)
91 {
92 const int width = 2 * m + 1 + 2 * m + 2, height = 4 * m - 1;
93 for ( int h = 0; h < height; ++h)
94 {
95 for ( int w = 0; w < width; ++w)
96 cout << h2o[h][w];
97 cout << endl;
98 }
99 }
100
101 int main()
102 {
103 ios::sync_with_stdio( false);
104 int m, cnt = 1;
105 for (;;)
106 {
107 cin >> m;
108 if (m == 0)
109 break;
110 int asmx[Mmx][Mmx];
111 char h2o[Max][Max];
112 memset(h2o, '*', sizeof(h2o));
113 for ( int h = 1; h <= m; ++h)
114 {
115 for ( int w = 1; w <= m; ++w)
116 cin >> asmx[h][w];
117 } // end of input
118 cout << "Case " << cnt++ << ':' << endl << endl;
119 draw_h2o(asmx, h2o, m);
120 print_h2o(h2o, m);
121 cout << endl;
122 }
123
124 return 0;
125 }
126
2
3 #include <iostream>
4 #include <cstring>
5
6 using namespace std;
7
8 const int Mmx = 13, Max = 1 << 7;
9
10 inline bool verify_atom( char h2o[Max][Max], int atom_y, int atom_x, int height, int width)
11 {
12 const int dy[] = { -1, 0, 1, 0 }, dx[] = { 0, 1, 0, -1 };
13 for ( int d = 0; d < 4; ++d)
14 {
15 int ny = atom_y + dy[d], nx = atom_x + dx[d];
16 if (nx <= 0 && nx >= width - 1 && ny < 0 && ny >= height - 1)
17 continue;
18 if (h2o[ny][nx] == '|' || h2o[ny][nx] == '-')
19 return false;
20 }
21 return true;
22 }
23
24 inline void draw_h2o( int asmx[Mmx][Mmx], char h2o[Max][Max], int m)
25 {
26 const int width = 2 * m + 1 + 2 * m + 2, height = 4 * m - 1;
27
28 for ( int w = 0; w < width; ++w)
29 h2o[0][w] = h2o[height - 1][w] = '*';
30 for ( int h = 1; h < height - 1; ++h)
31 {
32 for ( int w = 0; w < width; ++w)
33 {
34 if (w == 0 || w == width - 1)
35 h2o[h][w] = '*';
36 else
37 h2o[h][w] = ' ';
38 }
39 } // end: init h2o array
40
41 for ( int h = 1; h < height - 1; h += 4)
42 {
43 for ( int w = 1; w < width - 1; w += 4)
44 h2o[h][w] = 'H';
45 for ( int w = 3; w < width - 1; w += 4)
46 h2o[h][w] = 'O';
47 } // end: draw 'h'-and-'o' line
48
49 for ( int h = 3; h < height - 1; h += 4)
50 {
51 for ( int w = 3; w < width - 1; w += 4)
52 h2o[h][w] = 'H';
53 } // end: draw only-'h' line
54
55 for ( int h = 1; h <= m; ++h)
56 {
57 for ( int w = 1; w <= m; ++w)
58 {
59 int oxygen_h = 1 + 4 * (h - 1), oxygen_w = 3 + 4 * (w - 1);
60 if (asmx[h][w] == 1)
61 h2o[oxygen_h][oxygen_w - 1] = h2o[oxygen_h][oxygen_w + 1] = '-';
62 if (asmx[h][w] == -1)
63 h2o[oxygen_h - 1][oxygen_w] = h2o[oxygen_h + 1][oxygen_w] = '|';
64 } // end: draw h2o whose asmx equals 1 or -1
65 }
66
67 for ( int h = 1; h <= m; ++h)
68 {
69 for ( int w = 1; w <= m; ++w) if (asmx[h][w] == 0)
70 {
71 int oxygen_h = 1 + 4 * (h - 1), oxygen_w = 3 + 4 * (w - 1);
72 const int dh[] = { -1, -1, 1, 1 }, dx[] = { -1, 1, -1, 1 };
73 // up-left up-right down-left down-right
74 for ( int d = 0; d < 4; ++d)
75 {
76 int y1 = oxygen_h + dh[d], x1 = oxygen_w, y2 = oxygen_h, x2 = oxygen_w + dx[d];
77 if (y1 <= 0 || y1 >= height - 1 || x1 <= 0 || x1 >= width - 1 || y2 <= 0 || y2 >= height - 1 || x2 <= 0 || x2 >= width - 1)
78 continue;
79 if (verify_atom(h2o, y1 + dh[d], x1, height, width) && verify_atom(h2o, y2, x2 + dx[d], height, width))
80 {
81 h2o[y1][x1] = '|';
82 h2o[y2][x2] = '-';
83 break;
84 }
85 }
86 }
87 } // end: draw orthogonal h2o molecules (asmx = 0)
88 }
89
90 inline void print_h2o( char h2o[Max][Max], int m)
91 {
92 const int width = 2 * m + 1 + 2 * m + 2, height = 4 * m - 1;
93 for ( int h = 0; h < height; ++h)
94 {
95 for ( int w = 0; w < width; ++w)
96 cout << h2o[h][w];
97 cout << endl;
98 }
99 }
100
101 int main()
102 {
103 ios::sync_with_stdio( false);
104 int m, cnt = 1;
105 for (;;)
106 {
107 cin >> m;
108 if (m == 0)
109 break;
110 int asmx[Mmx][Mmx];
111 char h2o[Max][Max];
112 memset(h2o, '*', sizeof(h2o));
113 for ( int h = 1; h <= m; ++h)
114 {
115 for ( int w = 1; w <= m; ++w)
116 cin >> asmx[h][w];
117 } // end of input
118 cout << "Case " << cnt++ << ':' << endl << endl;
119 draw_h2o(asmx, h2o, m);
120 print_h2o(h2o, m);
121 cout << endl;
122 }
123
124 return 0;
125 }
126