题解 P2555 【[AHOI2002]数的朗读】

· · 题解

见过的最恶心的模拟

这个题题意非常明白,思路非常清晰,做法非常单一,但是就是很难做。。要注意的细节远远超乎预料。

各种细节的注意直接扔到代码里了,貌似也没有什么非常的地方和关键代码。实际上是因为处处都是关键代码。。。。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int z,flag,o,l,n,l1,d=-1,k,book,yi;
char ch[1001],ch1[101],shu[5];
int main()
{
    shu[1]='S';
    shu[2]='B';
    shu[3]='Q';//这里的处理可以凭个人喜好,我个人比较喜欢这么处理,后面也比较简洁。
    cin>>ch;//不要想当然的一个个读,正常情况下好像没问题,但是0一多就会错了,老老实实直接全读进来比较好,也可以用循环从1开始读入,有强迫症的自便。
    l=strlen(ch);
    for(int i=0;i<l;i++)
    {
        if(ch[i]=='+'||ch[i]=='-'||ch[i]=='0')//仔细读题,不仅只有符号和前缀0,还有“+”这个坑货。。。。
        {
            o++;//o用来记录你读完这些字符一共用了多长。
        }
        if(ch[i]=='.')
        {
            d=i;
            break;//如果前面全是0,又读到小数点,单独算一种情况。
        }
    }
    if(o==l)//极端情况之一,全是0,不要觉得这个很多余,因为出现+0000000000000这样的数也不是不可能。。
    {
        cout<<"0";
        return 0;
    }
    if(o==d)//这里就是第一种情况分支,如果是个小于1的小数,当成特殊情况处理。
    {
        cout<<"0";
        flag=1;//进行标记。
    }
    if(d==-1)//如果压根没有读到小数点,把小数点的位置标记为第l位。
    d=l;
    if(flag==1)//特殊处理<1的情况
    {
        cout<<"D";
        for(int i=o+1;i<l;i++)//从小数点下一位直接读到最后
        {
            cout<<ch[i];
        }
        return 0;
    }else//处理不是<1的情况
    {
        if(ch[0]=='-')//如果有负号(题目规定一定是第一个字符),先读出来
        {
            cout<<"F";
            k++;//当前读到的位数
        }else
        if(ch[0]=='+')//这个坑爹的+又出现了,必须特殊处理。。。。
        k++;
        while(ch[k]=='0')//处理掉所有的前缀0
        k++;
        for(int i=k;i<d;i++)
        {
            if(d-i>8)//如果此时剩下的位数多余8位,输出Y,数据保证不大于十亿,所以不用管之前有没有S什么的。
            {
                cout<<ch[i];
                cout<<"Y";
                continue;
            }
            if(d-i>5)//处理万级。
            {
                if(ch[i]!='0')//如果当前的数不是0,就要读出来
                {
                    if(book==1)//如果之前的一位是0,读出来那个0
                    {
                        cout<<"0";
                        cout<<ch[i];
                        if(d-i-1!=0)
                        cout<<shu[d-i-4-1];//这就是用1,2,3标记的原因,这里很好处理。。。
                        book=0;//把标记取消
                        yi=1;//确定这个数大于一万并且有一个不是0的数。
                    }else
                    {
                        cout<<ch[i];//如果前面没有0直接输出就可以了
                        if(d-i-1!=0)//如果这个数减出来不是0,就输出后面的,防止输出无用空格。
                        cout<<shu[d-i-4-1];
                        yi=1;
                    }
                }else
                {
                    book=1;//打上标记。
                }
                continue;
            }
            if(d-i==5)//当读到万位时由于有W特殊处理
            {
                if(d-k>8&&yi==0)//如果这个数在10亿以上并且万级全是0
                yi=0;//继续是0不用读了。
                else
                {    
                    if(ch[i]!='0')//如果当前位不是0
                    {
                        if(book==1)//刚才的标记现在还可以用
                        {
                            cout<<"0";
                            cout<<ch[i];
                            cout<<"W";//把万读出来
                            book=0;
                        }else
                        {
                            cout<<ch[i];//直接读
                            cout<<"W";
                        }
                    }else//直接读W,打上标记。
                    {
                    cout<<"W";
                    book=1;
                    }    
                    book=0;
                    continue;
                }
            }
            if(d-i<=4)//千位一下的就很好处理了
            {
                if(ch[i]!='0')
                {
                    if(book==1)
                    {
                        cout<<"0";
                        cout<<ch[i];
                        if(d-i-1!=0)
                        cout<<shu[d-i-1];
                        book=0;
                    }else
                    {
                        cout<<ch[i];
                        if(d-i-1!=0)
                        cout<<shu[d-i-1];
                    }
                }else
                {
                    book=1;
                }
            }
        }
        if(d!=l&&d!=l-1)//最后再处理一遍小数点。
        {
            cout<<"D";
            for(int i=d+1;i<l;i++)
            cout<<ch[i];//这才算真正结束了。
        }
    }
}

真是恶心的模拟

总而言之,这个题有耐心,总是能做出来的,毕竟什么高级算法都没用。。。。