• HDU 4294 A Famous Equation(DP)


    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4249

    题目大意:给一个a+b=c的表达式,但是a、b、c中部分位的数字丢失,并用?代替,问有多少种方案使得这个表达式成立。

    Sample Input
    7+1?=1?
    ?1+?1=22
     
    Sample Output
    Case 1: 3
    Case 2: 1
     
    Hint

    There are three solutions for the first case: 7+10=17, 7+11=18, 7+12=19 There is only one solution for the second case: 11+11=22 Note that 01+21=22 is not a valid solution because extra leading zeros are not allowed.

    分析:网上的代码有2种,第一种:

      状态dp[len][i][j][k]表示三个数a,b,c的len位上的三个数字i , j, k 。

      if((i+j)%10==k)  //上一位不进1

      dp[len][i][j][k]+=dp[len-1][ii][jj][kk];其中ii+jj==kk||ii+jj+1==kk

      if((i+j+1)%10==k)  //上一位进1

      dp[len][i][j][k]+=dp[len-1][ii][jj][kk];

      其中ii+jj>=10&&(ii+jj)%10==kk,ii+jj+1>=0,(ii+jj+1)%10==kk

      最后答案是sum(dp[len-1][i][j][k]), (i+j==k||i+j+1==k)

    代码如下:

      1 # include<iostream>
      2 # include<cstring>
      3 # include<cstdio>
      4 # include<stack>
      5 # include<algorithm>
      6 # define LL __int64     //如果需要改成long long 的话多么方便
      7 using namespace std;
      8 
      9 int len1,len2,len3,a[10],b[10],c[10];
     10 LL dp[10][10][10][10];
     11 stack<char >st;
     12 LL DP()
     13 {
     14     int i,j,k,l;
     15     memset(dp,0,sizeof(dp));
     16     for(i=0; i<10; i++)
     17     {
     18         if(a[0] != -1 && a[0] != i)     //枚举该位,如果不是?则必须是给定的数字i,不能枚举其他数
     19             continue;
     20         for(j=0; j<10; j++)
     21         {
     22             if(b[0] != -1 && b[0] != j)
     23                 continue;
     24             for(k=0; k<10; k++)
     25             {
     26                 if(c[0] != -1 && c[0] != k)
     27                     continue;
     28                 if((i+j)%10==k)
     29                     dp[0][i][j][k] = 1;
     30             }
     31         }
     32     }
     33     for(l=1; l<len3; l++)   //从和的倒数第2位开始枚举
     34     {
     35         for(i=0; i<10; i++)
     36         {
     37             if(a[l] != -1 && a[l] != i)
     38                 continue;
     39             if(l==len1-1 && i==0)   //首位不能是0
     40                 continue;
     41             if(l>=len1 && i!=0)     //和比加数多余的位,相当于在加数的前面加0
     42                 continue;
     43             for(j=0; j<10; j++)
     44             {
     45                 if(b[l] !=-1 && b[l] !=j)
     46                     continue;
     47                 if(l==len2-1 && j==0)
     48                     continue;
     49                 if(l>=len2 && j!=0)
     50                     continue;
     51                 for(k=0; k<10; k++)
     52                 {
     53                     if(c[l] != -1 && c[l] !=k)
     54                         continue;
     55                     if(l==len3-1 && k==0)
     56                         continue;
     57                     if((i+j)%10 !=k &&(i+j+1)%10!=k)      //因为对应位上的三个数字a+b=c或者a+b+1=c;是从前往后进位的
     58                         continue;
     59                     if((i+j)%10==k) //上一位不进1
     60                     {
     61                         for(int ii=0; ii<10; ii++)
     62                             for(int jj=0; jj<10; jj++)
     63                                 for(int kk=0; kk<10; kk++)
     64                                 {
     65                                     if(dp[l-1][ii][jj][kk] !=0 &&(ii+jj==kk||ii+jj+1==kk))
     66                                         dp[l][i][j][k] += dp[l-1][ii][jj][kk];
     67                                 }
     68                     }
     69                     if((i+j+1)%10==k)       //上一位进1
     70                     {
     71                         for(int ii=0; ii<10; ii++)ii+jj
     72                             for(int jj=0; jj<10; jj++)
     73                                 for(int kk=0; kk<10; kk++)
     74                                 {
     75                                     if(dp[l-1][ii][jj][kk] !=0 &&(((ii+jj>=10 && (ii+jj)%10==kk))||(ii+jj+1>=10 &&(ii+jj+1)%10==kk)))
     76                                         dp[l][i][j][k] += dp[l-1][ii][jj][kk];
     77                                 }
     78                     }
     79                 }
     80             }
     81         }
     82     }
     83     LL ans = 0;
     84     for(i=0; i<10 ; i++)
     85         for(j=0; j<10; j++)
     86             for(k=0; k<10; k++)
     87             {
     88                 if(dp[len3-1][i][j][k] != 0 && (i+j==k || i+j+1==k))
     89                     ans += dp[len3-1][i][j][k];
     90             }
     91     return ans;
     92 }
     93 int main()
     94 {
     95     char s[50];
     96     int cas=1;
     97     while(~scanf("%s",s))
     98     {
     99         int i,len = strlen(s);
    100         memset(a,0,sizeof(a));
    101         memset(b,0,sizeof(b));
    102         memset(c,0,sizeof(c));
    103         for(i=0; s[i]!='+'; i++)
    104             st.push(s[i]);
    105         len1 = 0;
    106         while(!st.empty())  //提取第一个加数,逆序存放到a数组里边,这样进位就是从前往后进位
    107         {
    108             if(st.top() != '?')
    109                 a[len1++] = st.top()-'0';
    110             else a[len1++] = -1;
    111             st.pop();
    112         }
    113         for(i++; s[i] != '='; i++)
    114             st.push(s[i]);
    115         len2 = 0;
    116         while(!st.empty())  //提取第2个加数
    117         {
    118             if(st.top() != '?')
    119                 b[len2++] = st.top() - '0';
    120             else b[len2++] = -1;
    121             st.pop();
    122         }
    123         for(i++; i<len; i++)
    124             st.push(s[i]);
    125         len3 = 0;
    126         while(!st.empty())  //提取第3个加数
    127         {
    128             if(st.top() != '?')
    129                 c[len3++] = st.top() - '0';
    130             else c[len3++] = -1;
    131             st.pop();
    132         }
    133         printf("Case %d: %I64d
    ",cas++,DP());
    134     }
    135     return 0;
    136 }
  • 相关阅读:
    易股(私募) 笔试
    TinyWS
    重载 隐藏 重写(覆盖)
    vector emplace_back() 和push_back() 的区别
    std::ref 和 std::cref 的使用
    网络 I/O复用模式之select、poll、epoll
    网络I/O中 同步/异步 阻塞/非阻塞 概念
    git 使用方法 (reset merge rebase stash diff等)
    C++11 thread用法
    C++中 锁的使用 互斥锁:std::mutex std::lock_guard std::unique_lock ,读写锁使用shared_mutex ,条件变量使用std::condition_variable类
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/3305967.html
Copyright © 2020-2023  润新知