hdu 2054 A == B ? 解题报告

本文详细阐述了解决复杂数值比较问题的过程,包括处理正负号、前导零、后置零等细节,并深入探讨了调试过程中遇到的错误,如数组越界和非法内存访问。通过实例分析,提供了严谨的解决思路和代码实现,最终通过AC验证算法正确性。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2054

      这是目前以来我写的最长的代码!所以看到这篇报告的读者,如果自问耐心不是过人的话,还是不要看代码了,建议只看思路。这是很久以前遗留下来的题目,wa了一次之后就放下了,因为知道会很繁琐,不是单纯短短几行代码就搞定的(那时天真的做法啊~~)。几天前,心血来潮,决定把它干掉!!!前前后后做了足足3天,其实没那么夸张啦,加起来应该7、8个小时左右吧(不好意思,说了那么多废话),步入正题。

      这道题目题意很简单:就是判别A是否等于B。不过有很多细节需要注意,我就是看着人家给的测试数据才知道的,辛辛苦苦地写出来,提交之后遇到我有史以来的第一个Runtime Error(ACCESS_VIOLATION),什么来的,百度之......RE一般有几种情况:1)数组越界  2)访问非法内存(什么来的?) 3)除以0   4)堆栈溢出...... 我十分确定是第2种情况,但是我不知道如何查错,于是请教乌冬师兄,超级好人,叫我发代码来(N长的都愿意看,真的是感动万分啊~~),原来是用了goto语句。之所以用goto,是因为觉得不需要用太多标志变量,break只能跳一重循环,而goto可以跳几重。还有一个致命的错误是,goto(用了两次)的出口用了两个相同的变量h,不过在不同的函数块里。他说goto语句是全局跳跃,会破坏整体结构,说用goto是坏习惯,建议用break,能跳出最近一个循环 ,或者return(长见识了,好感动)。删掉之后,wa了。因为有很多变态的数据过不了!!!

     题目的解决思路大体上是:1、正负号问题    2、前导0   3、后置0

     还有一些特别的输入要考虑,输入的第一个字符是 的情况,这里我是把它放在正负号的函数里解决的。最折磨我的是几种情况没考虑到

     1、len1(a的长度),len2(b的长度)是变化的!!因为在解决这些小问题的过程中,有可能增添数据(例如,.1234变成0.1234,长度就增加1),或者消去数据(000.456变成0.456,长度减少2)

     2、由基础不扎实导致的!字符'0'、0、'\0'(C++中字符串的结尾标志,存储在字符串的结尾)要区分清楚。上面已经提到len是会改变的,也就是字符型数组的长度是会变的,因此结尾要赋予0,作为字符串的结尾标志。字符'0'是当.123变0.123的时候才用到的。

     在网上看到其实只需要处理很少情况就可以AC的,不过为了严谨,我就很啰嗦地考虑了很多种情况。discuss中很奇葩的数据都过了。以下是AC代码:

  1 #include <iostream>
  2 #include <string.h>
  3 using namespace std;
  4 
  5 const int MAXN = 100000 + 10; //MAXN的长度要足够大,少一个0都不行
  6 char a[MAXN], b[MAXN];
  7 bool asign, bsign; //记录a、b的正负号
  8 int len1, len2;
  9 
 10 void as()
 11 {
 12     int i;
 13     if (a[0] == '-' || a[0] == '+')
 14     {
 15         if (a[0] == '-')
 16             asign = false;
 17         else
 18             asign = true;
 19         for (i = 0; i < len1-1; i++) //新的数组不要存储符号
 20             a[i] = a[i+1];
 21         a[i] = 0;    //赋予数组结束标志
 22         len1--;     //少了符号位长度减1
 23     }
 24     if (a[0] == '.')
 25     {
 26         for (i = len1; i >= 1; i--)  //整个数组向后移,为首位插入字符0做准备
 27             a[i] = a[i-1];
 28         a[i] = '0';
 29         len1++;  //多了字符0之后长度加1
 30     }
 31     if (isdigit(a[0]))  //没正负号的表示是正数
 32         asign = true;
 33 /*    cout << "a[j] = " << a << endl;
 34     cout << "alen = " << len1 << endl; */
 35 }
 36 
 37 void bs()
 38 {
 39     int i;
 40     if (b[0] == '-' || b[0] == '+')
 41     {
 42         if (b[0] == '-')
 43             bsign = false;
 44         else
 45             bsign = true;
 46         for (i = 0; i < len2-1; i++)
 47             b[i] = b[i+1];
 48         b[i] = 0;
 49         len2--;
 50     }
 51     if (b[0] == '.')
 52     {
 53         for (i = len2; i >= 1; i--)
 54             b[i] = b[i-1];
 55         b[i] = '0';
 56         len2++;
 57     }
 58     if (isdigit(b[0]))
 59         bsign = true;
 60 /*    cout << "b[j] = " << b << endl;
 61     cout << "blen = " << len2 << endl; */
 62 }
 63 
 64 void a_beforzero()
 65 {
 66     int i, j, pos, count;
 67     i = count = 0;  //count的设置很重要,用了统计去掉多少个前导0
 68     while (a[i] == '0')
 69     {
 70         i++;
 71         count++;
 72     }
 73     pos = i;   
 74     j = 0;
 75     if (!isdigit(a[i]))  //a[i] = '.’的情况
 76     {
 77         a[j++] = '0';
 78         for ( ; pos < len1; pos++)
 79             a[j++] = a[pos];
 80         len1++;
 81     }
 82     else
 83     {
 84         while (pos < len1)
 85             a[j++] = a[pos++];
 86     }
 87     a[j] = 0;
 88     len1 -= count;
 89 /*    cout << "a[j] = " << a << endl;
 90     cout << "alen = " << len1 << endl; */
 91 }
 92 
 93 void b_beforzero()
 94 {
 95     int i, j, pos, count;
 96     i = count = 0;
 97     while (b[i] == '0')
 98     {
 99         i++;
100         count++;
101     }
102     pos = i;
103     j = 0;
104     if (!isdigit(b[i]))
105     {
106         b[j++] = '0';
107         for ( ; pos < len2; pos++)
108             b[j++] = b[pos];
109         len2++;
110     }
111     else
112     {
113         while (pos < len2)
114             b[j++] = b[pos++];
115     }
116     b[j] = 0;
117     len2 -= count;
118 /*    cout << "b[j] = " << b << endl;
119     cout << "blen = " << len2 << endl; */
120 }
121 
122 void a_backzero()
123 {
124     int i, j;
125     for (i = 0; i < len1; i++)
126     {
127         if (a[i] == '.')
128         {
129             j = len1-1;
130             while (a[j] == '0')
131                 j--;
132             if (a[j] == '.' ) //去掉后置0有可能是123.的情况,此时要在'.'的位置增添结束标志
133                 a[j] = 0;
134             else
135                 a[++j] = 0;  //是数字的情况就在后一位加结束标志
136             break;
137         }
138     }
139 /*    cout << "a[j] = " << a << endl;    
140     cout << "alen = " << len1 << endl; */
141 }
142 
143 void b_backzero()
144 {
145     int i, j;
146     for (i = 0; i < len2; i++)
147     {
148         if (b[i] == '.')
149         {
150             j = len2-1;
151             while (b[j] == '0')
152                 j--;
153             if (b[j] == '.')
154                 b[j] = 0;
155             else
156                 b[++j] = 0;
157             break;
158         }
159     }
160 /*    cout << "b[j] = " << b << endl;
161     cout << "blen = " << len2 << endl; */
162 }
163 
164 int main()
165 {
166     while (scanf("%s%s", a, b) != EOF)
167     {
168         len1 = strlen(a);
169         len2 = strlen(b);
170         as();
171         bs();
172         a_beforzero();
173         b_beforzero();
174         a_backzero();        
175         b_backzero();
176         if (asign == bsign && strcmp(a, b) == 0)
177             printf("YES\n");
178         else
179             printf("NO\n");
180         memset(a, 0, sizeof(a));
181         memset(b, 0, sizeof(b));
182     }
183     return 0;
184 }

 

 

 

转载于:https://www.cnblogs.com/windysai/archive/2013/04/28/3049965.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值