题意:
就是有 n 个数字板,知道每个数字板现在还有哪些长条(块)还是亮的,你知道原来还有k个长条也是亮的,原来的数字最大是多少,如果拼不出一个数字就输出-1
思路:
想到直接爆搜,但是比赛时疯狂T7,还是太菜了。。。。。早上起来看了下别人才知道加个最大后缀和最小的前缀剩下的长条数量在最大后缀和最小后缀之间才去搜,否则不搜;代码直接用比赛时代码改的,巨丑
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
const int N = 2010;
const int inf = 0x3f3f3f3f;
string str[10] = {"1110111", "0010010", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011"};
int n,k;
string ans;
int s[N];
int st[150][15];
int mi_suf[N],mx_suf[N];//后缀和
string ss[10] = {"0","1","2","3","4","5","6","7","8","9"};
int f(string s1,string s2){
int res = 0;
for(int i = 0;i < 7;i++){
if(s2[i] == '1'&&s1[i]=='0')
res++;
}
return res;
}
//s1要变s2
int check(string s1,string s2){
int res = 0;
for(int i = 0;i < 7;i++){
if(s2[i]=='0'&&s1[i]=='1') return -1;
else if(s2[i] == '1'&&s1[i]=='0') res++;
}
return res;
}
void dfs(int dep,string state,int remain){
if(dep > n){
if(remain==0){
for(int i = 0;i < state.size();i++){
printf("%c",state[i]);
}
exit(0);
}
}else{
for(int i = 9;i >= 0;i--){
if(st[s[dep]][i]!=-1){
if(st[s[dep]][i] <= remain&&remain>=mi_suf[dep]&&remain<=mx_suf[dep]){
dfs(dep+1,state+ss[i],remain-st[s[dep]][i]);
}
}
}
}
}
void init(){
for(int s = 0;s < (1<<7);s++){
string sta = "";
for(int i = 0;i < 7;i++){
int x = (s>>i)&1;
if(x == 0) sta +="0";
else sta += "1";
}
for(int i = 0;i <= 9;i++){
st[s][i] = check(sta,str[i]);
}
}
}
int main(){
init();
scanf("%d%d",&n,&k);
ans = "";
string tmp;
for(int i = 1;i <= n;i++){
cin>>tmp;
int res = 0;
for(int i = 0;i < 7;i++){
if(tmp[i] == '1'){
res+=(1<<(i));
}
}
s[i] = res;
}
for(int i = 1;i <= n;i++){
mi_suf[i] = inf;mx_suf[i] = -1;
for(int j = 0;j <= 9;j++){
if(st[s[i]][j] != -1){
mi_suf[i] = min(mi_suf[i],st[s[i]][j]);
mx_suf[i] = max(mx_suf[i],st[s[i]][j]);
}
}
}
for(int i = n;i >= 1;i--){
mi_suf[i] += mi_suf[i+1];
mx_suf[i] += mx_suf[i+1];
}
dfs(1,"",k);
puts("-1");
return 0;
}