codeforces 509C C. Sums of Digits(数位dp+贪心+枚举)

题目链接:

codeforces 509C

题目大意:

给出一个序列,代表原序列对应位置数的每一位的数字之和,原序列单调递增,问原序列的最后一个数最小的方案每一个数是多少。

题目分析:

  • 首先对于每一个数,我们都采取比前一个数大的最小的方案,那么我们得到的最后一个数一定是最大的。
  • 假设b[]为给出的序列,a[]为原序列,我们求取这种方案的方法如下:
    • 如果 bi>bj (i>j) ,那么直接从低位到高位利用多出的部分填充,每一位填充到9之后再填充更高的数位。
    • 否则,我们就从小到大枚举每一位,因为只要它加一,后面的就不管如何排,都会比卡年的大,而且当前这种情况,我们将最低位填充到9,一定会得到最小的新的方案。如果当前后面的位不足以补足,那么当前枚举的这一位不合法,继续枚举,如果能够补足,我们一定是选取比当前枚举的位低的最高的位优先减值来进行补足。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 500

using namespace std;

int s[2][MAX];
int len[MAX];
int n,a[MAX];

void print ( int i )
{
    int x = i%2;
    for ( int j = len[i]-1 ; j >= 0 ; j-- )
        printf ( "%d" , s[x][j] );
    puts ("");
}

int main ( )
{
    while ( ~scanf ( "%d" , &n ) )
    {
        for ( int i = 0 ; i < n ; i++ )
            scanf ( "%d" , &a[i] );
        memset ( len , 0 , sizeof ( len ));
        int temp = a[0];
        while ( temp )
        {
            if ( temp > 8 )
            {
                 s[0][len[0]++] = 9;
                 temp -= 9;
            }
            else
            {
                s[0][len[0]++] = temp;
                temp = 0;
            }
        }
        s[0][len[0]] = 0;
        print ( 0 );
        for ( int i = 1 ; i < n ; i++ )
        {
            int x = i%2;
            int y = (i-1)%2;
            memset ( s[x] , 0 , sizeof ( s[x] ));
            if ( a[i] > a[i-1] )
            {
                int d = a[i]-a[i-1];
                int j = 0;
                while ( d )
                {
                    int tt = s[y][j];
                    if ( s[y][j] != 9 )
                    {
                        if ( d >= 9-tt )
                        {
                            d -= 9 -tt;
                            s[x][len[i]++] = 9;
                        }
                        else
                        {
                            s[x][len[i]++] = tt+d;
                            d = 0;
                        }
                    }
                    else s[x][len[i]++] = 9;
                    j++;
                }
                for ( int k = j ; k < len[i-1] ; k++ )
                    s[x][len[i]++] = s[y][k];
            }
            else
            {
                 int d = a[i-1]-a[i]+1;
                 for ( int j = 1 ; j <= len[i-1] ; j++ )
                 {
                     int sum = -d;
                     for ( int k = j-1 ; k >= 0 ; k-- )
                     {
                         int tt = s[y][k];
                         sum += tt;
                     }
                     if ( sum < 0 ) continue;
                     for ( int k = 0 ; k < j ; k++ )
                     {
                         if ( sum >= 9 )
                         {
                             s[x][k] = 9;
                             sum -= 9;
                         }
                         else
                         {
                             s[x][k] = sum;
                             sum = 0;
                         }
                     }
                     if ( sum == 0 && s[y][j] != 9 )
                     {
                         s[x][j] = s[y][j]+1;
                         if ( j == len[i-1] ) len[i] = len[i-1]+1;
                         else len[i] = len[i-1];
                         for ( int k = j+1 ; k < len[i] ; k++ )
                            s[x][k] = s[y][k];
                         break;
                     }
                 }
            }
            print ( i );
        }
    }
}

你可能感兴趣的:(枚举,codeforces,贪心,数位dp)