Codeforces Round #637 (Div. 2) - D. Nastya and Scoreboard

题目链接

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 << '\n';
        return ;
    }
    cout << "-1\n";
}
int main() {
    int T = 1;
    // scanf("%d", &T);
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    while(T --) 
        solve();
    return 0;
}

posted @ 2020-07-11 22:29  pyoxiao  阅读(81)  评论(0编辑  收藏  举报