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


题意:一个n个数码位的分数板,每一个数码位都是一个七段数码管,现在给出每个数码位的显示情况,问再点亮k段数码管的话能显示的最大的数是多少,如果不能构成一串数字,就输出-1.

答案允许有前导0,但是有前导0的时候答案长度必须要跟n一致

原题链接:https://codeforces.ml/contest/1341/problem/D


开始感觉是贪心去爆搜,但是显然这会T,所以想了几分钟后就果断放弃了爆搜的想法。后边想了个dp,dp[i][j]表示构造到第i位时点亮j根数码管能显示最大的数,但这个也有个问题,你dp的类型是数值的话2000位的大整数你肯定装不下,可是如果是string类型这么dp下来复杂度会达到O(n3),就在这里卡着我没想出一个好的解决办法。

后来比赛结束后看了下standing第一大佬的代码,不得不感叹大佬的nb,虽然也是dp,但是他是dp[i][j]表示从后面构造到第i位数码位时点亮j根数码管能否构成数字,然后从第一位数码位开始贪心构造就行了。

系统地说算法的步骤吧。

第一步:预处理0~9对应数码位字符串状态成整数(状态压缩)

第二步:输入数据,并处理出每一位当前数码位所对应的整数形式的状态

第三步:定义enable[i][j]表示从最后一位数码位往前构造到第i位数码位时点亮j根数码管能否构造出数字

第四步:设置enable[n+1][0] = true,这是dp初始状态,意义是开始构造数码位时点亮了0根数码管。

第五步:for i = n -> 1,然后第i个数码位可以构造出数字num的话就算出要点亮几根数码管diff,然后for j = diff -> k,如果enable[i+1][j-diff]是true,则enable[i][j] = true。也就是能从之前已构造好的数字上再构造出这个数字的话enablep[i][j]就可以设成真

第六步:如果enable[1][k] = false,也就是说构造到第1位时点亮k段数码管无法成功构造成数字的话那么我们就输出-1

第七步(如果没输出-1):根据enable我们可以轻松构造出答案的字符串


AC代码:

#include <bits/stdc++.h>
#define rep(i, l, r) for(long long i=l; i<=r ;i++)
using namespace std;

typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
ll gcd(ll n, ll m) { return n % m == 0 ? m : gcd(m, n % m);}

const int Maxn = 2e3 + 10;
bool enable[Maxn][Maxn];
string Number[10] = {"1110111", "0010010", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011" };
int val[10];
int dval[Maxn];

void Ini()
{
    rep(i, 0, 9)
        rep(j, 0, 6)
            if(Number[i][j] == '1') val[i] |= 1 << (7-j-1);
}

void Input(int& n, int& k)
{
    cin>>n>>k;
    rep(i, 1, n){
        string s;
        cin>>s;
        rep(j, 0, 6)
            if(s[j] == '1') dval[i] |= 1 << (7-j-1);
    }
}

void solve(int n, int k)
{
    enable[n+1][0] = true;
    for(int i=n; i>=1 ;i--)
        for(int j=9; j>=0 ;j--){
            if((val[j] & dval[i]) == dval[i]){
                int diff = __builtin_popcount(val[j] ^ dval[i]);
                for(int kk=diff; kk<=k ;kk++)
                    enable[i][kk] |= enable[i+1][kk-diff];
            }
        }

    if(!enable[1][k]){
        cout<<-1<<endl;
        return;
    }

    string ans = "";
    int remain = k;
    for(int i=1; i<=n ;i++)
        for(int j=9; j>=0 ;j--){
            if((val[j] & dval[i]) == dval[i]){
                int diff = __builtin_popcount(val[j] ^ dval[i]);
                if(enable[i+1][remain - diff]){
                    ans += j + '0';
                    remain -= diff;
                    break;
                }
            }
        }

    cout<<ans;
}

int main()
{
    ios::sync_with_stdio(false);
    //freopen("data.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);

    Ini();
    int n, k;
    Input(n, k);
    solve(n, k);

    return 0;
}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM