Problem I Rank LED题解
题目大意
‘0’到‘9’的数字亮线依次为{6、2、5、5、4、5、6、3、7、6}。
Luras想修改每条光线的位置,使她的新等级尽可能小,同时新等级也是一个不带任何前导零的正整数。
另外,光线总数应与开始时相同。
官方题解
思路
这题一开始想的是无脑换成8结尾,但发现不行,比如 输入 23 输出 22
还是得用dp来解,当然可以尝试打表看看有没有规律啥的
使用 dp 通过打表发现规律(发现208及其之后的都是以8结尾)
所以可以用比较偷懒的写法:把208(灯管长度18)之前的保存起来,当特例判断。之后的就直接贪(只要判断其中几个数字就行),直接从后往前输出
参考代码c++(官方题解思路dp写法)
感谢 2023牛客寒假集训营训练营3 QQ群的 [文件]第十五届蓝桥杯国赛获奖名单.pdf 同学的DP代码
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int N = 7e2 + 5;
string dp[N];
int t, n;
string s;
vector<string> a = {"1", "7", "4", "2", "0", "6", "8"};
vector< int > b = { 2, 3, 4, 5, 6, 6, 7 };
int arr[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
string MinStr(string a, string b) {
if (a[0] == 'f') {
return b;
}
if (a.size() < b.size()) {
return a;
}
if (a.size() > b.size()) {
return b;
}
for (int i = 0; i < int(a.size()); i++) {
if (a[i] < b[i]) {
return a;
}
if (a[i] > b[i]) {
return b;
}
}
return a;
}
string Merge(string a, string x) {
string str = "";
if (x[0] == '0') {
str += a[0];
str += x;
for (int i = 1; i < int(a.size()); i++) {
str += a[i];
}
return str;
}
bool flag = true;
for (int i = 0; i < int(a.size());) {
if (flag && x[0] <= a[i]) {
flag = false;
str += x;
} else {
str += a[i++];
}
}
if (flag) {
str += x;
}
return str;
}
int main() {
for (int i = 0; i <= 700; i++) {
dp[i] = "f";
}
dp[2] = "1", dp[3] = "7", dp[4] = "4", dp[5] = "2", dp[6] = "6", dp[7] = "8";
for (int i = 8; i <= 700; i++) {
for (int j = 0; j < int(a.size()); j++) {
dp[i] = MinStr(dp[i], Merge(dp[i - b[j]], a[j]));
}
}
// dp输出所有结果
// for (int i = 0; i <= 70; i++) {
// cout << dp[i] << '\t';
// if (i % 10 == 9) {
// cout << endl;
// }
// }
cin >> t;
while (t--) {
cin >> n >> s;
int x = 0;
for (int i = 0; i < int(s.size()); i++) {
x += arr[s[i] - '0'];
}
cout << dp[x] << endl;
}
return 0;
}