Sicily 1628. Extended Normal Order Sort

心理健全的不要做这道题,一定会后悔的:题目透露的信息太少,而一些关键问题却不做任何解释。我整整纠结了三天三夜才把题目没有说的,而样例又需要的用到的内容弄清楚。
简言之,从题目可知:
1.小写字母按大写字母来处理;
2.若一个加减号在一个数字的前面,而不在一个数字的后面,那这个加减号表示正负;
3.一般字符按ASCⅡ码来处理。
明白了这三点,离AC还很远,因为这只是说明表明了数字和数字,字符和字符的比较,但关键是数字和字符的比较(不是说了按ASCⅡ码比较吗?你自己试下吧,WA你到死)。
久经折磨后,我弄到了两份AC代码,分析过后都发现有明显的逻辑漏洞,只要简单的把输入的两个字符串交换下位置,AC就变WA,尽管测试题目给出的样例并没有出错。这说明了题目最后的系统检测也是很有问题的,貌似这道题还是大纽约赛区的题目…… 
废话少说,关键只有一点:预处理字符串,将其格式统一规范(我怎么想到的?我还真 不知道我怎样明白过来的)。预处理包括:
1.数值为0的子字符串(0、00、+00、-0等等)全部删去;
2.表示数字的的子字符串,统一在前面加上加(减)号表示正(负);
3.小写字母全部转换成大写字母;
然后在比较的时候,若是当前位置都是数字,比较数字大小;否则,若都是表示正负的加减号,减号优先;其余的情况,按照ASCⅡ码进行比较(请自行想象如果没有预处理,而直接按上述原则进行比较,答案会发生怎样的变化,典型的是0+1和1的比较);
把这些都考虑了,你就可以华丽丽地AC了,即使是交换了输入的顺序,也照样AC不误。

Run Time: 0sec
Run Memory: 312KB
Code length: 2080Bytes
Submit Time: 2011-11-29 22:44:08

// Problem#: 1628
// Submission#: 1016810
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
using namespace std;

bool issign( char s[] , int i ) {
    return ( i == 0 || !isdigit( s[ i - 1] ) ) && ( s[ i ] == '+' || s[ i ] == '-' ) && isdigit( s[ i + 1 ] );
}

void formalize( char s[] ) {
    int i, j;
    static char temp[ 1000 ];

    for ( i = 0, j = 0; i < strlen( s ); i++, j++ ) {
        if ( isdigit( s[ i ] ) ) {
            if ( i == 0 || ( s[ i - 1 ] != '+' && s[ i - 1 ] != '-' ) )
                temp[ j++ ] = '+';
            while ( s[ i ] == '0' )
                i++;
            while ( isdigit( s[ i ] ) )
                temp[ j++ ] = s[ i++ ];
            if ( temp[ j - 1 ] == '+' || temp[ j - 1 ] == '-' )
                j--;
        }
        temp[ j ] = ( s[ i ] >= 'a' && s[ i ] <= 'z' ? s[ i ] - 32: s[ i ] );
    }
    temp[ j ] = '\0';
    strcpy( s, temp );
}

int cmp( char s1[], char s2[] ) {
    static int len1, len2;

    formalize( s1 );
    formalize( s2 );
    for ( int i = 1, j = 1; i < strlen( s1 ) && j < strlen( s2 ); i++, j++  ) {
        if ( isdigit( s1[ i ] ) && isdigit( s2[ j ] ) ) {
            int k = i;
            while ( isdigit( s1[ k ] ) )
                k++;
            len1 = k - i;
            k = j;
            while ( isdigit( s2[ k ] ) )
                k++;
            len2 = k - j;

            if ( len1 != len2 )
                return ( len1 < len2 ? -1: 1 );
            else {
                while ( i < k && j < k ) {
                    if ( s1[ i++ ] != s2[ j++ ] )
                        return ( s1[ i ] < s2[ j ] ? -1: 1 );
                }
            }
        }

        if ( s1[ i ] != s2[ j ] ) {
            if ( issign( s1, i ) && issign( s2, j ) )
                return ( s1[ i ] == '-' ? -1: 1 );
            return ( s1[ i ] < s2[ j ] ? -1: 1 );
        }
    }

    return 0;

}


int main()
{
    int N, i;
    char s1[ 1000 ], s2[ 1000 ];

    cin >> N;
    for ( i = 1; i <= N; i++ ) {
        scanf( "%s%s", s1, s2 );
        cout << i << " " << cmp( s1, s2 ) <<  endl;
    }

    return 0;

}                                 


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值