题意:0~9每个数字由不同数量位置的火柴棍组成,一共n组数字,让你添加k根火柴棍,使n组数字可以构造的最大的数。若不能构成任何数,那么输出 -1
dp[i][j] 第i个数时,还剩下j个火柴棍,dp[i][j] = 1代表这个状态是可以构成的。那么初始值 dp[n+1][0] = 1代表 n+1个数时,剩下0个火柴棍的状态是1。从后往前推可以达到的状态,最后从前往后贪心得到结果。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define ff(i,a,b) for(int i = a; i <= b; i++)
#define f(i,a,b) for(int i = a; i < b; i++)
typedef pair<int,int> P;
#define ll long long
string num[10],s[2010];
int a[2010][10],sum[2010],dp[2010][2010];
int solve(int x, int y)
{
int numm = 0;
ff(i,0,6)
{
if(s[x][i] == '1' && num[y][i] == '0') return 1e9;
else if(s[x][i] == '0' && num[y][i] == '1') numm++;
}
return numm;
}
int main()
{
ios::sync_with_stdio(false);
num[0] = "1110111";num[1] = "0010010";
num[2] = "1011101";num[3] = "1011011";
num[4] = "0111010";num[5] = "1101011";
num[6] = "1101111";
num[7] = "1010010";
num[8] = "1111111";
num[9] = "1111011";
int n,k;
cin >> n >> k;
ff(i,1,n)
{
cin >> s[i];
ff(j,0,9)
a[i][j] = solve(i,j);
}
memset(dp,0,sizeof(dp));
dp[n+1][0] = 1;
for(int i = n; i >= 1; i--)
{
for(int kk = 0; kk <= 9; kk++)
for(int j = k; j >= a[i][kk]; j--)
{
dp[i][j] |= dp[i + 1][j - a[i][kk]];
}
}
string ans;
int now = k,flag;
ff(i,1,n)
{
flag = 0;
for(int j = 9; j >= 0; j--) if(now >= a[i][j] && dp[i + 1][now - a[i][j]]) { now = now - a[i][j];ans += '0' + j; flag = 1; break;}
if(!flag) break;
}
if(!flag) puts("-1");
else cout << ans << endl;
return 0;
}