[CF1340B] Nastya and Scoreboard

[CF1340B] Nastya and Scoreboard - dp,贪心

Description

(n) 个如下图所示的灯组原件,构成了一个计分板。每个灯组原件由 (7) 个灯管组成,编号如下图所示。现在这 (n) 个灯组原件中,有一些灯管保持常亮,求再点亮恰好 (k) 个灯管,能够组成的最大的数是多少。

Solution

考虑一个带贪心性质的 DP,从低位往高位做,记录前 i 个数,j 次操作,能否表示一个数(并记录能表示的最大的数),至于过程状压一下位运算判断就好

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2005;

const int masks[] = {119, 18, 93, 91, 58, 107, 111, 82, 127, 123};

int n, k, f[N][N], a[N], from[N][N], dig[N][N];

signed main()
{
    f[0][0] = 1;
    cin >> n >> k;
    for (int i = n; i >= 1; i--)
    {
        bitset<7> bs;
        cin >> bs;
        a[i] = bs.to_ulong();
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= k; j++)
        {
            for (int c = 0; c < 10; c++)
            {
                if ((~masks[c]) & a[i])
                    continue;
                int delta = masks[c] & (~a[i]);
                int cost = __builtin_popcount(delta);
                if (j < cost)
                    continue;
                if (f[i - 1][j - cost] == 0)
                    continue;
                f[i][j] = 1;
                from[i][j] = j - cost;
                dig[i][j] = c;
            }
        }
    }
    if (f[n][k] == 0)
    {
        cout << -1 << endl;
        return 0;
    }
    else
    {
        int p = k;
        for (int i = n; i >= 1; i--)
        {
            cout << dig[i][p];
            p = from[i][p];
        }
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14568845.html