/* 这题用了挺久才彻底明白题意...值得特别注意的一点是,输入数据中,是将同一个Disk作为一个横排输入的,但是入门经典上的表格,是将同一个Disk作为一个竖列输入的...因此用了很久才明白,为什么数据会是这样 T^T 题意的说明可参考: http://blog.csdn.net/xienaoban/article/details/52164099 我的代码是参考了题解: http://blog.csdn.net/wcr1996/article/details/43834545 一些说明: 1.三重循环以输出十六进制的部分,十分精妙的应该时不时理清思路从头再想一次再敲一次 2.注意如入门经典P98的图所示,在输出时,对同一个部分,枚举d个Disk中的s个字节数字,再进入下一部分,直到b部分循环完毕,故而循环的嵌套顺序应为:对部分的循环 => 对磁盘的循环 -> 对区间的每个bit的循环 3.还有要注意下,每个磁盘是有 b*s 个bit放置数据的,在三层循环的最后一层,即确定某一个disk中的bit的位置时,借助区间数目b做乘法,会更加容易,这也是最外层循环b的真正原因 自己曾经踩过/差点踩下的坑: 1. if (i % d == j) 处,考虑到i和j的范围,千万不要把i、j弄混了,即使样例数据不会有错,但是,也要注意到 b的上限是比d要大的,在 b 大于 d的情况下若将i j 位置交换,就一定WA了 */
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int d, s, b, n; const int maxn = 6500; char a[7][maxn]; bool parity; // 1 odd; 0 even bool read() { cin >> d; if (!d) return false; cin >> s >> b; getchar(); //加上这句话十分关键,否则就WA了!!!因为会把换行符作为 ch memset(a, 0, sizeof(a)); char ch = getchar(); parity = ch == 'O'; if (ch == ' ') cout << "Wrong Answer because of this fault!!!" << endl; getchar(); n = s * b; for (int i = 0; i < d; i++) cin >> a[i]; return true; } bool solve() { int i, j; for (i = 0; i < n; i++) //对每列做检查,看是否需要恢复数据,以及检查是否满足所给校验规律 { bool flag = false; int broke = -1; // 用来标记是否出现两次x,若是则退出,无法恢复 for (j = 0; j < d; j++) { char &ch = a[j][i]; // 用引用,则数据的使用和修改都非常方便 if (ch == '1') flag = !flag; if (ch == 'x') { if (broke == -1) broke = j; else return false; } } if (broke == -1 && flag != parity) return false; //磁盘没有损坏,不需恢复,但校验不合法 if (broke != -1) a[broke][i] = (parity == flag) ? '0':'1'; // 恢复 } return true; } void print(bool ch) { if (!ch) { cout << "invalid." << endl; return; } else cout << "valid, contents are: "; int cnt = 0, sum = 0; for (int i = 0; i < b; i++) //枚举硬盘被分为的b个部分 { int pos = i * s; for (int j = 0; j < d; j++) { if (i % d == j) continue; //若为校验位,应该跳过 for (int k = 0; k < s; k++) { sum <<= 1; sum += a[j][pos + k] == '1'; cnt++; if (cnt == 4) { printf("%X", sum); sum = 0; cnt = 0; } } } } // 若最后一个数不满4位,不能直接构成16进制,则末尾补0 if (cnt) printf("%X", sum << (4 - cnt)); cout << endl; } int main() { int kase = 0; while (read()) { cout << "Disk set " << ++kase << " is "; print(solve()); } return 0; }