贪心枚举,代码里的注释很详细
/* ***********************************************
Author :CKboss
Created Time :2015年02月06日 星期五 15时31分06秒
File Name :CF509C.cpp
************************************************ */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
int n;
int b[333];
int pos[333];
int num[333][500];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",b+i);
pos[0]=1;
/// 第一个数 贪心
int temp=b[1];
if(temp==0) num[1][pos[1]++]=0;
while(temp>0)
{
if(temp>=9) { temp-=9; num[1][pos[1]++]=9; }
else { num[1][pos[1]++]=temp; temp=0; }
}
/// 剩下的数 贪心
for(int i=2;i<=n;i++)
{
int lastsum=b[i-1];/// 上一位的已经确定的数字和
bool flag=false;
for(int j=0;flag==false;j++) /// 枚举位置
{
if(j-1>=0) lastsum-=num[i-1][j-1];
///枚举所在的位加多少
for(int k=num[i-1][j]+1;k<=9&&flag==false;k++)
{
int add = k-num[i-1][j];
/// 剩下的数的范围可以在 0 ~ 9*j 之间
if(j-1>=0)
{
if(lastsum+add<=b[i]&&lastsum+add+9*j>=b[i]) /// 成功
{
flag=true;
pos[i]=max(j+1,pos[i-1]);
/// 贪心部分的值 val
int val = b[i]-lastsum-add;
int tn=0;
while(val>0)
{
if(val>=9) { val-=9; num[i][tn++]=9; }
else { num[i][tn++]=val; val=0; }
}
/// 枚举的那一位
num[i][j]=k;
/// 如果存在的不变部分
for(int kk=j+1;kk<pos[i-1];kk++)
{
num[i][kk]=num[i-1][kk];
}
}
}
else /// 在j==0时特殊考虑
{
if(lastsum+add==b[i]) /// 成功
{
flag=true;
pos[i]=pos[i-1];
for(int kk=0;kk<pos[i];kk++)
{
num[i][kk]=num[i-1][kk];
}
num[i][j]=k;
}
}
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=pos[i]-1;j>=0;j--)
printf("%d",num[i][j]);
putchar(10);
}
return 0;
}