题意:开始给出每个数字的点亮状态,问能否再点亮k个块,使其成为一连串的数字且数字尽量的大
先预处理出每个数字初始状态能否变成某个数字且需点亮几个块
从后往前DP,dp[i][j]表示从第i个到最后一个可以正好用j个块
然后从前往后贪心,能取大的就取大的
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
char s[2005][10];
char op[10][10]={
"1110111","0010010","1011101","1011011","0111010","1101011","1101111","1010010","1111111","1111011"};
ll c[2005][15],dp[2005][2005],ans[20005];
ll query(ll x,ll y)
{
ll cnt=0;
for(int i=0;i<7;i++)
{
if(s[x][i]=='1'&&op[y][i]=='0')
{
return -1;}
if(s[x][i]=='0'&&op[y][i]=='1')
{
cnt++;}
}
return cnt;
}
int main()
{
ll n,k,w;
scanf("%lld %lld",&n,&k);
for(int i=0;i<n;i++)
{
scanf("%s",s[i]);}
for(int i=0;i<n;i++)
{
for(int j=0;j<10;j++)
{
c[i][j]=query(i,j);}
}
for(int oo=0;oo<10;oo++)
{
if(c[n-1][oo]!=-1)
{
w=c[n-1][oo];
dp[n-1][w]=1;
}
}
for(int i=n-2;i>=0;i--)
{
for(int j=0;j<=k;j++)
{
if(dp[i+1][j]==1)
{
for(int oo=0;oo<10;oo++)
{
w=c[i][oo];
if(w!=-1)
{
dp[i][w+j]=1;}
}
}
}
}
if(dp[0][k]==0)
{
printf("-1\n");
return 0;
}
for(int i=0;i<n;i++)
{
for(int j=9;j>=0;j--)
{
w=c[i][j];
if(i==n-1&&w!=-1&&w==k)
{
ans[i]=j;break;
}
if(w!=-1&&dp[i+1][k-w]==1)
{
k-=w;
ans[i]=j;
break;
}
}
}
for(int i=0;i<n;i++)
{
printf("%lld",ans[i]);}
printf("\n");
return 0;
}