zoukankan      html  css  js  c++  java
  • UVa12105

    这道题题意不说,直接上思路:

    根据n<=100可以看出答案可能为50位(111111......)所以对于longlong来说是存不下,所以我们设计状态要尽量避免数据过大,这对

    空间或时间来说都是一种考验,我们用d(i,j)表示除以m余j的i位数所需要最少火柴数,所以状态转移方程为:

    (此处采用刷表法) d[i+1][(j*10+k)%m] = min(d[i+1][(j*10+k)%m],d[i][j]+c[k])

    然后我们通过这样需要最大的数,首先最大的数一定满足位数最大,在位数最大的基础上满足从高位到低位数最大,

    所以我们首先需要找到d[i][0]不是INF(在这里如果当前位凑不成我们设为INF),在此基础上我们从9-0去试,然后求出900....%m的数n,

    然后满足d[i-1][m-n]+c[9]<=n,如果满足要求9就可以,然后依次类推,注意细节以及dp初始化。

    下面是实现:

    // UVa 12105
    #include <cstdio>
    #include <cstring> 
    #include <algorithm>
    using namespace std; 
    
    const int maxn = 50 + 5; // 100 / 2 
    const int maxm = 3000 + 5; 
    const int INF = 10000000003; 
    const int c[] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6}; 
    
    int n, m;
    int d[maxn][maxm], p[10][maxn]; 
    
    void init() {
      for (int i = 0; i < 10; ++i) p[i][1] = i % m; 
      for (int i = 2; i <= n / 2; ++i)
        for (int j = 0; j < 10; ++j) 
          p[j][i] = p[j][i-1] * 10 % m;    
    }
    
    void print_ans() { 
      int Max_len, Vis = 1, M = 0; 
      for (Max_len = n / 2; Max_len >= 0; --Max_len) if (d[Max_len][0] != INF) break; 
      while (Max_len) {
        for (int i = 9; i >= 0; --i) {
          int mode = (p[i][Max_len]+M) % m; 
          if (d[Max_len-1][(m-mode)%m]+c[i] <= n) {
            printf("%d", i); 
            n -= c[i]; 
            M = mode;  
            Vis = 0;    
            break; 
          }
        }
        Max_len--; 
      }
      if (Vis) printf("-1"); 
    }
    
    int main() { 
        int kase = 0; 
        while (scanf("%d", &n) == 1 && n) {
          scanf("%d", &m); 
          init();
          for (int i = 0; i <= n / 2; ++i) 
            for (int j = 0; j < m; ++j) 
              d[i][j] = INF; 
          d[0][0] = 0; 
          for (int i = 0; i <= n / 2; ++i) 
            for (int j = 0; j < m; ++j) if (d[i][j] != INF)    
              for (int k = 0; k < 10; ++k) {
                int N = c[k] + d[i][j]; 
                d[i+1][(j*10+k)%m] = min(N, d[i+1][(j*10+k)%m]);    
              }
          printf("Case %d: ", ++kase);  
          print_ans(); 
          printf("
    "); 
        }
        return 0;
    }
  • 相关阅读:
    『转』QueryPerformanceFrequency()
    『转』C++中虚析构函数的作用
    存储过程的优缺点
    一个工作7年的软件工程师的总结(收藏)
    存储过程分页算法(收藏)
    Ajax原理(收藏)
    七大秘籍成就职场王者(收藏)
    视图的优缺点
    SQL索引全攻略
    .aspx、MasterPage、.ascx加载顺序
  • 原文地址:https://www.cnblogs.com/yifeiWa/p/11298819.html
Copyright © 2011-2022 走看看