题目链接
https://codeforces.com/contest/1341/problem/D
tag
(dp), 贪心
solution
首先我们求出每一位数字转换成(0-9)所需要打开灯的数量,如果不能转换,即我们需要关闭灯才能转换成该数字,置为无穷大,(cost[i][j])表示第(i)位数字转换至数字j的花费,(dp[i][j])表示第i个数字到第(n)个数字打开(j)个灯能否使得第(i-n)这几个数形成一个合法数字序列,
状态转移:初值置为(false),置边界(dp[n+1][0] = true)
if(dp[i][j] && j + cost[i - 1][digit] <= k) dp[i - 1][j + cost[i - 1][digit]] = true
如果(dp[1][k] = false), 那么表示(1-n)打开(k)栈灯无法形成合法的数字序列,即答案为(-1)
否则我们从前往后,从第一位开始往后贪心的选取,每位选取最大且能使后一位合法的数字,这样能保证选取出来的数字最大,又因为(dp[1][k] ==true)所以必然存在一种合法的答案,贪心的选取输出即可
code
//created by pyoxiao on 2020/07/09
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define CL(a, b) memset(a, b, sizeof(a))
using namespace std;
const int mod = 1e9 + 7, INF = 0x3f3f3f3f;
LL fpow(LL a, LL b, LL p = mod){LL ans = 1; a %= p; while(b) {if(b & 1) ans = ans * a % p; b >>= 1; a = a * a % p;} return ans;}
LL gcd(LL a, LL b){return b == 0 ? a : gcd(b, a % b);}
const string sticks[10] = {"1110111", "0010010", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011"};
const int N = 2e3 + 7;
int n, k;
string s;
int cost[N][10];
bool dp[N][N];
void solve() {
cin >> n >> k;
for(int i = 0; i < n; i ++) {
cin >> s;
for(int j = 0; j < 10; j ++) {
for(int bit = 0; bit < 7; bit ++) {
if(s[bit] == '0' && sticks[j][bit] == '1') cost[i][j] ++;
else if(s[bit] == '1' && sticks[j][bit] == '0'){ cost[i][j] = INF; break;}
}
}
}
dp[n][0] = 1;
for(int i = n; i >= 1; i --) {
for(int j = 0; j <= k; j ++) if(dp[i][j]) {
for(int bit = 0; bit < 10; bit ++) {
if(cost[i - 1][bit] + j <= k) {
dp[i - 1][j + cost[i - 1][bit]] = 1;
}
}
}
}
if(dp[0][k]) {
for(int i = 0; i < n; i ++) {
for(int j = 9; j >= 0; j --) {
if(k >= cost[i][j] && dp[i + 1][k - cost[i][j]]) {
cout << j;
k -= cost[i][j];
break;
}
}
}
cout << '
';
return ;
}
cout << "-1
";
}
int main() {
int T = 1;
// scanf("%d", &T);
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
while(T --)
solve();
return 0;
}