现在的位置: 首页 > 综合 > 正文

【DP】 hdu4249 A Famous Equation

2018年04月25日 ⁄ 综合 ⁄ 共 2493字 ⁄ 字号 评论关闭

A Famous Equation

http://acm.hdu.edu.cn/showproblem.php?pid=4249



Problem Description
Mr. B writes an addition equation such as 123+321=444 on the blackboard after class. Mr. G removes some of the digits and makes it look like “1?3+??1=44?”. Here “?” denotes removed digits. After Mr. B realizes some digits are missing, he wants to recover them.
Unfortunately, there may be more than one way to complete the equation. For example “1?3+??1=44?” can be completed to “123+321=444” , “143+301=444” and many other possible solutions. Your job is to determine the number of different possible solutions.
 


Input
Each test case describes a single line with an equation like a+b=c which contains exactly one plus sign “+” and one equal sign “=” with some question mark “?” represent missing digits. You may assume a, b and c are non-negative integers, and the length of each
number is no more than 9. In the other words, the equation will contain three integers less than 1,000,000,000.
 


Output
For each test case, display a single line with its case number and the number of possible solutions to recover the equation.
 


Sample Input
7+1?=1? ?1+?1=22
 


Sample Output
Case 1: 3 Case 2: 1

题意:给一个包含'?'的等式,问这个等式可能有多少种

题解:dp[i][0]代表第i位满足条件且不进位的方法数,dp[i][1]代表第i位满足条件且进位的方法数。

然后枚举每个'?'可能的值,值的范围(以a为例)起点:a[i]=='?'    是  i不是最高位或者a只有个位   ?1:0

                                                                                                   否 a[i]

                                                                           终点:a[i]=='?'    是  9

                                                                                                    否 a[i]

其他的就是各种判断了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
LL dp[15][2];//dp[i][0]代表第i位满足条件且不进位的方法数,dp[i][1]代表第i位满足条件且进位的方法数
int a[15],b[15],c[15];
char s[50];
int al,bl,cl;
int main()
{
    for(int l,cas=1;~scanf("%s",s);++cas)
    {
        al=bl=cl=0;
        memset(dp,0,sizeof(dp));
        //下面的清零很重要啊,因为这个一直WA...
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        for(l=0;s[l]!='+';++l)
        {
            if(s[l]=='?') a[al++]=-1;
            else a[al++]=s[l]-'0';
        }
        for(l=l+1;s[l]!='=';++l)
        {
            if(s[l]=='?') b[bl++]=-1;
            else b[bl++]=s[l]-'0';
        }
        for(l=l+1;l<strlen(s);++l)
        {
            if(s[l]=='?') c[cl++]=-1;
            else c[cl++]=s[l]-'0';
        }
        //a,b有一个的数字长度大于c
        if(cl<bl||cl<al)
        {
            printf("Case %d: 0\n",cas);
            continue;
        }
        reverse(a,a+al);
        reverse(b,b+bl);
        reverse(c,c+cl);
        for(int i=0;i<cl;++i)
            for(int j=(a[i]<0?((i<al-1||al==1)?0:1):(a[i]));j<=(a[i]<0?9:a[i]);++j)
                for(int k=(b[i]<0?((i<bl-1||bl==1)?0:1):(b[i]));k<=(b[i]<0?9:b[i]);++k)
                {
                    LL add;
                    if((c[i]<0||((j+k+1)%10==c[i])))
                    //上一位进位的情况
                    {
                        add=(i>0?dp[i-1][1]:0);
                        if(j+k+1>=10) dp[i][1]+=add;
                        else          dp[i][0]+=add;
                    }
                    if((c[i]<0&&(i!=cl-1))||(c[i]<0&&(i==cl-1)&&(j+k>0))||(cl==1&&c[i]<0)||((j+k)%10==c[i]))
                    //上一位没有进位的情况
                    {
                        add=(i>0?dp[i-1][0]:1);
                        if(j+k>=10) dp[i][1]+=add;
                        else        dp[i][0]+=add;
                    }
                }
        printf("Case %d: %I64d\n",cas,dp[cl-1][0]);
    }
    return 0;
}

【上篇】
【下篇】

抱歉!评论已关闭.