D - Nastya and Scoreboard
题意:给你n串由0和1组成的长度为7的字符串,n串表示一个n位数,每个串的第n个位置有1则表示这个位置的火柴是亮着的,
位置的表示如下图所示,而每个数字可以由指定位置上的火柴组成,给你每个位上已有火柴的位置,再给你k根火柴,问你由这k
根火柴和已有火柴组成的数字,最大是多少。
解题思路 :用cnt[ i ][ j ]表示第i个字符串要表示为数字j所需要的火柴数量。用DFS进行搜索,运用dp记忆化来去掉很多不需要
的情况即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define MOD 998244353
#define INF 0x3f3f3f3f
#define mem(a,x) memset(a,x,sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
int cnt[2005][10];
int dp[2005][2005];
char mp[10][10]={"1110111","0010010","1011101","1011011","0111010","1101011","1101111","1010010","1111111","1111011"};
string s;
int n,m;
vector<int>v;
int dfs(int n,int x,int sum) //n=总行数 x=行数 sum=使用的个数
{
if(m-sum<0)return 0;
if(x-1==n&&sum==m)return 1;
else if(x-1==n&&sum!=m)return 0;
if(dp[x][sum]!=-1)return dp[x][sum];
for(int i=9;i>=0;i--){
if(cnt[x][i]>=0){
if(dfs(n,x+1,sum+cnt[x][i])){
v.push_back(i);
return dp[x][sum]=1;
}
}
}
dp[x][sum]=0;
return 0;
}
int main()
{
scanf("%d %d",&n,&m);
mem(cnt,0);
mem(dp,-1);
for(int i=1;i<=n;i++){
cin>>s;
for(int k=0;k<=9;k++){
for(int j=0;j<7;j++){
if(s[j]=='1'&&mp[k][j]=='0'){
cnt[i][k]=-INF;
break;
}else{
if(s[j]=='0'&&mp[k][j]=='1'){
cnt[i][k]++;
}
}
}
}
}
dfs(n,1,0);
if(v.size()==0){
cout<<"-1"<<endl;
}else{
for(int i=v.size()-1;i>=0;i--){
cout<<v[i];
}
}
return 0;
}