思路:先确定每个位置上变成0~9需要额外点亮多少灯,因为需要用完k个灯,可以有前导零,我们从最后一位开始点亮灯,往前递推可行的方案。dp[当前位置][用了j个灯] = (可行,不可行)。
然后就判断能不能用完k个灯,可以得话从前往后以9~0顺序寻找最大数字。
1 #include <cstdio> 2 #include <iostream> 3 #include <cstdio> 4 #include <algorithm> 5 #include <functional> 6 #include <set> 7 #include <vector> 8 #include <queue> 9 #include <cstring> 10 #include <stack> 11 12 using namespace std; 13 14 #define ll long long 15 #define pb push_back 16 #define fi first 17 #define se second 18 19 string digits[10] = { "1110111", "0010010", "1011101", "1011011", "0111010", 20 "1101011", "1101111", "1010010", "1111111", "1111011" }; 21 22 void solve(){ 23 int n, k; 24 cin >> n >> k; 25 vector<string > s(n); 26 for(auto& str : s) cin >> str; 27 vector<vector<int > > dist(n + 1, vector<int>(10 )); 28 for(int i = 0; i < n; ++i){ 29 for(int d = 0; d < 10; ++d){ 30 for(int j = 0; j < 7; ++j){ 31 char x = s[i][j]; 32 char y = digits[d][j]; 33 if(x == '1' && y == '0'){ 34 dist[i][d] = -1; 35 break; 36 } 37 if(x == '0' && y == '1'){ 38 ++dist[i][d]; 39 } 40 } 41 } 42 } 43 44 vector<vector<int > > dp(n + 1, vector<int >(k + 1)); 45 dp[n][0] = 1; 46 for(int i = n; i > 0; --i){ 47 for(int j = 0; j <= k; ++j){ 48 if(dp[i][j]){ 49 for(int d = 0; d < 10; ++d){ 50 if(dist[i - 1][d] != -1 && j + dist[i - 1][d] <= k){ 51 dp[i - 1][j + dist[i - 1][d]] = 1; 52 } 53 } 54 } 55 } 56 } 57 if(dp[0][k] == 0) cout << "-1" << endl; 58 else{ 59 int now = -1; 60 for(int i = 0; i < n; ++i){ 61 for(int d = 9; d >= 0; --d){ 62 if(dist[i][d] != -1 && k >= dist[i][d] && dp[i + 1][k - dist[i][d]]){ 63 now = d; 64 k -= dist[i][d]; 65 break; 66 } 67 } 68 cout << now; 69 } 70 cout << endl; 71 } 72 } 73 74 int main(){ 75 76 // freopen("C:\Users\admin\Desktop\input.txt", "r", stdin); 77 // freopen("C:\Users\admin\Desktop\output.txt", "w", stdout); 78 ios::sync_with_stdio(false); 79 cin.tie(0); 80 cout.tie(0); 81 solve(); 82 83 return 0; 84 } 85