• UVA


    /*
      这题用了挺久才彻底明白题意...值得特别注意的一点是,输入数据中,是将同一个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;
    }


  • 相关阅读:
    性能相关记录
    邮箱SMTP
    IntelliJ IDEA 14.1.7 安装激活
    pychram永久激活
    电脑的奇葩坑
    jmeter过程中的坑
    各数据库驱动连接配置
    spring定时器--时间设置规则
    linux redhat7.2下vim的安装与使用方法
    分数化小数
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789474.html
Copyright © 2020-2023  润新知