[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];
}
}
}