Codeforces Round #637 (Div. 2)(D、Nastya and Scoreboard DP、DFS)(训练)

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;
}
越自律,越自由
原文地址:https://www.cnblogs.com/ha-chuochuo/p/13435576.html