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