子序列的总和

时间:2012-01-08 13:36:10

标签: algorithm

考虑第一个整数是A,A [i]等于A的第i个数字(基于0的索引,从右到左),第二个整数是B,B [i]等于第i个数字B(基于0的索引,从右到左)。

A和B的幸运总和等于C,C [i] = max(A [i],B [i])。如果i大于或等于整数大小,则第i个数字等于0.

例如,

  1. 幸运总和47和729是

    max(7,9)=9
    max(4,2)=4
    max(0,7)=7
    answer = 749
    
  2. 同样,幸运总和W =(74,92,477)

    max(4,2) = 4
    max(7,9) = 9
    Lucky sum of 74,92 = 94
    Lucky sum of W=(Lucky sum of (94,477))
    

    max(4,7)=7
    max(9,7)=9
    max(0,4)=4
    
  3. 所以w的幸运总和= 497。

    任务: 我们得到一个数组W,包含n(1< = n< = 50)个整数。

    我们必须找到W的一些非空子序列,以便该子序列中的整数幸运总和为幸运数字 幸运数字是正整数,其十进制表示仅包含幸运数字4和7.例如,数字47,744,4是幸运的,5,17,467不是。)。

    约束:0< W [i]< 1E9

    示例:

    1. W = {4,7}:answer = 3
    2. W = {43,47,44}:answer = 2
    3. 动态编程可以解决这个问题吗?

      如何在C ++中有效解决这个问题?

2 个答案:

答案 0 :(得分:0)

因为答案的每一点都是独立的。因此,请单独更新它们,整个算法需要O(n*log10(w))

这是我刚写的代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

#define MAXL 15

using namespace std;

int n;
int ans[MAXL];

int main(){
    int i,j,w;
    scanf("%d",&n);
    memset(ans,0,sizeof(ans));
    while (n--){
        scanf("%d",&w);
        i = 0;
        while (w>0){
            j = w % 10;
            ans[i] = max(ans[i], j);
            i++;
            w /= 10;
        }
    }
    bool flag = false;
    for (i=MAXL-1;i>=0;i--){
        if (ans[i] > 0) flag = true;
        if (flag) printf("%d",ans[i]);
    }
    printf("\n");
    return 0;
}

答案 1 :(得分:0)

这是我能想到的(尚未完成):

DP 位掩码一起使用。我们现在用以下方式表示一个数字:每个位分为五种:

  1. (0) - &gt; 0
  2. (1,2,3) - &gt; 1
  3. (4) - &gt; 2
  4. (5,6) - &gt; 3
  5. (7) - &gt; 4
  6. (8,9) - &gt; -1
  7. 我们可以很容易地看到,只要有8或9位,它就永远不会被添加到有效的解决方案中。现在我们使用位掩码来表示数字,这需要5^8

    因此,我们让f[i][s]表示我们可以从first i numbers中选择子集的总方式来计算出数字whose bit-mask is s

    这是我刚才写的代码.....
    还剩下三件事:

    1. __int64使用long longint代替f[][]
    2. 使用queue来加速枚举,如果我们使用for (i = 0;i < MAXS;i++)进行枚举,则存在很多不可能的状态(即f [] [s] == 0)。
    3. 使用f [0..1] [MAXS]降低内存成本。
    4. 示例代码:

      #include <queue>
      #include <cstdio>
      #include <cstring>
      #include <algorithm>
      
      #define MAXN 51
      #define MAXS 390625 //5^8
      
      using namespace std;
      
      const int exp[] = {1, 5, 25, 125, 625, 3125, 15625, 78125, 390625};
      int n;
      int w[MAXN];
      struct node{
          int i;
          int stat;
          node(int x, int y):i(x),stat(y){}
      };
      queue<node> q;
      __int64 f[MAXN][MAXS];
      bool inq[MAXN][MAXS];
      
      int main(){
          //freopen("test.txt","r",stdin);
          memset(f,0,sizeof(f));
          memset(inq,0,sizeof(inq));
          scanf("%d",&n);
          for (int i = 0;i < n;i++) scanf("%d",&w[i]);
          while (!q.empty()) q.pop();
          f[0][0] = 1;
          for (int i = 0;i < n;i++)
              for (int j = 0;j < MAXS;j++)
                  if (f[i][j] > 0){
                      f[i + 1][j] += f[i][j];
                      int stat = j;
                      int loc = 0;
                      int k = 0;
                      for (int p = w[i];p > 0;p /= 10){
                          k = p % 10;
                          if (k <= 0) k = 0;
                              else if (k <= 3) k = 1;
                                  else if (k <= 4) k = 2;
                                      else if (k <= 6) k = 3;
                                          else if (k <= 7) k = 4;
                                              else k = -1;
                          if (k < 0) break;
                          int bit = stat % exp[loc + 1] / exp[loc];
                          if (k < bit) k = bit;
                          stat = stat - (bit - k) * exp[loc];
                          loc++;
                      }
                      if (k < 0) continue;
                      f[i + 1][stat] += f[i][j];
                  }
          int ans = 0;
          for (int i = 0;i < MAXS;i++){
              bool flag = false;
              for (int loc = 7;loc >= 0;loc--){
                  int bit = i % exp[loc + 1] / exp[loc];
                  if (bit > 0) flag = true;
                  if (flag == true && (bit != 2 && bit != 4)){
                      flag = false;
                      break;
                  }
              }
              if (flag == true) ans += f[n][i];
          }
          printf("%d\n",ans);
          return 0;
      }