POJ 1016 模拟 (改了最久的一道题,我服了orz)

题目链接:http://poj.org/problem?id=1016

 

这是我有史以来改过最久的一道题,一道模拟题,题目很简单 但是让我WA住的地方很傻比。。。长个记性吧。我服了

 

题目大意: 

 

现在有一个规则,给定一个数,统计其中数字(0~9)出现的次数,然后从小到大重新组成一个数。如112233,其中1出现2次,2出现2次,3出现2次,那么新的数为212223.现在有一个位数至多为80位的数,通过变换后根据题目中给定的输出的规定进行输出。
1.n is self-inventorying 
2.n is self-inventorying after j steps 
3.n enters an inventory loop of length k 
4.n can not be classified after 15 iterations
如果一个数变换一次过后仍为本身按1输出,如果不为本身,但是经过n(n<=15)次变换后为原来的数,则按2输出,如果超过15次仍未出现,但是在这15次变换中有数是相同的,求出这个相同两个数的最小长度,然后按3输出,最后若15次变换内没有出现上述每一种条件,则按4输出。需要注意的是先要执行上面的情况后才能考虑下面的情况。

 

分析:

模拟过程即可。

 

下面是我的代码:

#include <iostream>
#include<cstring>
#include<string>
#include<map>
#include<cstdio>
#include<cstdlib>
using namespace std;
int main()
{
//    freopen("in.txt","r",stdin);
    ios::sync_with_stdio(false);
    string s;
    while(cin>>s)
    {
//        cout<<"ssssssssss"<<s<<endl;
//cout<<9+'0'<<endl;
        if(s=="-1") break;
        map<int,int>  mp;
        for(int i=0;i<=9;i++)
            mp[i]=0;
        int len=s.size();
        for(int i=0;i<len;i++)
        {
            mp[s[i]-'0']++;
        }
//        cout<<mp[9]<<endl;
//        int flag=1;
//        for(int i=0;i<=9;i++)
//            {
//                if(mp[i]>80)  根本不用判断什么大于不大于80位!
//                    {flag=0;break;}
//            }
        cout<<mp[9]<<endl;
//        if(flag==0) { cout<<s<<" can not be classified after 15 iterations"<<endl; continue;}
        int kase=0;
        int T=0;
        string a[20];
        a[0]=s;
        int t=0;
        string s1=s;
        int xiabiao=0;
        int len2=0;
//        if(flag)
//        {
            while(1)
            {
                kase++;
                if(kase>15) break;
                string s2;
                for(int i=0;i<=9;i++)
                {
//                    if(i==1)
//                        cout<<"-----"<<mp[1]<<endl;
//                        cout<<char(10+'0')<<endl;
//                        cout<<char(9+'0')<<endl;
                    if(mp[i]!=0)
                    {
                        if(mp[i]>9)
                        {
                            int num=mp[i];
                            s2+=num/10+'0';
                            s2+=num%10+'0';
                            s2+=i+'0';
                        }
                        else{
                        s2+=mp[i]+'0';
                        s2+=i+'0';}
                    }
                }
//                cout<<"kase="<<kase<<"   "<<s2<<endl;
                t++;
                a[t]=s2;
//                cout<<"one  "<<kase<<endl;

                if(s2==s1) break;
                else
                {
                   for(int i=0;i<t;i++)
                   {
                       if(a[i]==s2)
                       {T=1;xiabiao=i;break;}
                   }
                   if(T==1) break;
                }
    //            mp.clear();
                for(int i=0;i<=9;i++)
                    mp[i]=0;
                s1.clear();
                s1=s2;
//                cout<<"s1="<<s1<<endl;
                len2=s1.size();
                for(int i=0;i<len2;i++)
                {
                    mp[s1[i]-'0']++;
                }
//                for(int i=0;i<=9;i++)
//                    cout<<mp[i]<<",";
//                cout<<endl;
            }
//        }
//        cout<<"kase="<<kase<<endl;
        if(kase>15)
            cout<<s<<" can not be classified after 15 iterations"<<endl;
        else if(kase==1)
            cout<<s<<" is self-inventorying"<<endl;
        else
        {
            if(T)
                cout<<s<<" enters an inventory loop of length "<<kase-xiabiao<<endl;
            else
                cout<<s<<" is self-inventorying after "<<kase-1<<" steps"<<endl;
        }
    }
    return 0;
}

 我的代码太乱太长了  实验课的时候写的 后来改的乱七八糟。 一开始是因为数字的个数有可能大于两位数,当大于两位数转换成字符时,  例如  cout<<char(10+'0')<<endl;时,我以为的输出结果是10,而实际上结果是  “:”符号!所以说明这方面我还有漏洞 根本没意识到这个问题  导致我改了这么久 也导致了   边界80的问题。通过这一道题改了这么长时间能看的出我还存在很多方面的问题  尤其是比较基础的细节问题 ,这些问题由于我平时不注意 导致了在比赛或者上课做题的时候一直WA。 以后还是要通过多做题  查缺补漏 。 谭琳老师说的那句话真的很对,犯错才会让你进步的很快,我现在懂了。

 

下面是网上参考的代码,和我写的差不多,都用到了string,需要向他学习的是 他的代码非常简洁,而且用到了函数(这题确实用函数做会简介很多,因为要多次求下一个的字符串)。而且我感觉也没必要用map 用char也完全解决问题了,用map虽然没有错,但看了别人的发现感觉自己用map多此一举了。。向别人学习吧。

 

AC代码:传送门

#include<iostream>
#include<string>
using namespace std;
#define maxn 100
string SelfString(string str)
{
    int i, a[10]={0};
    string s;
    for(i=0; i<str.length(); i++)
        a[str[i]-'0']++;
    for(i=0; i<10; i++)
    {
        if(a[i])
        {
            while(a[i])
            {
                s += a[i]%10+'0';
                a[i] /= 10;
            }
            s += i+'0';
        }
    }
    return s;
}
int main()
{
    string str;
    while(cin >> str, str != "-1")
    {
        string a[maxn];
        int i, j, k=1, ans=0;
        a[0] = str;
        for(i=1; i<=15; i++)
        {
            a[i] = SelfString(a[i-1]);
            if(a[i] == a[i-1])
            {
                ans = 1;
                break;
            }
            for(j=0; j<i; j++)
                if(a[i] == a[j])
                {
                    ans = 2;
                    break;
                }
            if(j < i)
                break;
        }
        if(ans==1 && i==1)
            cout << a[0] <<" is self-inventorying "<<endl;
        else if(ans==1)
            cout << a[0] <<" is self-inventorying after "<< i-1 <<" steps "<<endl;
        else if(i <= 15)
            cout << a[0] <<" enters an inventory loop of length " << i-j <<endl;
        else
            cout << a[0] << " can not be classified after 15 iterations" <<endl;
    }
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值