ZOJ 2202 α编码

///////////////////////////////////////////////////
// 1677474 2008-10-25 14:46:52 Accepted  2202 C++ 0 192 VRS
//计算编码后再译码的种数
//利用分治法,把字符串s二分为s1和s2,再把两部分的种数相乘
//注意情况:合并s1和s2时,考虑相邻接的两数可以组成一个编码,还有对0的多种情况的讨论
#include<iostream>
#include<string>
using namespace std;
char s[10000];

 

 

bool conbine(char s[],int l,int r)        //判断两数是否可以编码,可以返回1,否则返回0
{
    if(s[l]>'2' || s[l]=='0') return 0;
    if(s[l]=='2' && s[r]>'6') return 0;
    return 1;
}

 

long Acode(char s[],int l,int r)      //二分递归计算种数
{
    long mid,ansl,ansr,ans;
    if(l==r) return 1;               //1个数时返回1
    if(l+1==r)                       //2个数的情况
        if(s[r]=='0')                //当第二个数是0时,只有一种编码
            return 1;
        else
            return conbine(s,l,r)+1;
    if(l+2==r)                        //3个数的情况
        if(s[l+1]=='0' || s[r]=='0')  // 当第二或第三个数是0时,只有一种编码
            return 1;
        else
            return conbine(s,l,l+1)+conbine(s,l+1,r)+1;
    mid=(r-l+1)/2-1+l;                   //l与r的中值
    if(s[mid+1]=='0')                 //当s2的首元素是0,如“1101”,不用计算s[mid]和s[mid+1]分开
    {                                 //的两部分种数
        ansl=Acode(s,l,mid-1);
        ansr=Acode(s,mid+2,r);
        return ansl*ansr;
    }
    ansl=Acode(s,l,mid);
    ansr=Acode(s,mid+1,r);
    ans=ansl*ansr;
    if(s[mid+2]=='0')  return ans;   //当出现如“1011011”的情况时,由于s2的首元素"1"要和其后的
                                     //"0"组成一个编码,所以不须考虑s[mid]和s[mid+1]组成一编码的情况
    if(conbine(s,mid,mid+1))        
    {
        ansl=Acode(s,l,mid-1);
        ansr=Acode(s,mid+2,r);
        return ans+ansl*ansr;
    }
    else return ans;
}

 

 

int main()
{
    int len;
    while(cin>>s && s[0]!='0')
    {
        len=strlen(s);
        cout<<Acode(s,0,len-1)<<endl;
    }
    return 0;
}

 

你可能感兴趣的:(ZOJ)