D. Nastya and Scoreboard

链接:https://codeforces.com/contest/1341/problem/D

题意;给出n个字符串,k个操作。

   每个字符串表示一个残缺的数字,我们可以用若干个操作把这个数字补成(0~9)中的其中任意一个数字

   我们需要恰好补齐k个操作;

   假如不能补齐,就输出-1

   假如能补齐,就输出能够构成的最大的那个数

思路:这道题很容易想到用dfs的方法来做

   在dfs之前,我们需要预处理一下,每一个字符串变成(0~9)的需要的操作数;

   然后dfs的时候,我们自然是从最优情况开始枚举

   最优情况就是从大到小(因为要我们求出最大值)

   然后逐一枚举即可;

   但是,这样子dfs会超时。

   可以发现,dfs的过程中,有一些情况下是会重复的,我们把这些情况记录下来,下次再遇到这种情况,就直接得出答案退出即可

   这种情况跟数位DP类似(在本代码中记忆化为dp数组)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int inf=0x3f3f3f3f;
 4 const int maxn=2e3+10;
 5 int d[20][20];
 6 char mp[maxn][20];
 7 int dp[maxn][maxn];
 8 int cnt[maxn][maxn];
 9 vector<int>num;
10 int solve(int n,int now,int ls,int k)
11 {
12     if(ls>k) return 0;  //假如目前操作数已经大于k  就退出
13     if(n==now-1&&k==ls) return 1;       //满足情况,赋值为1,退出
14     else if(n==now-1&&k!=ls) return 0;  //不满足,赋值为0,退出
15     if(dp[now][ls]!=-1) return dp[now][ls]; //记忆化
16     for(int i=9;i>=0;i--){  //从大到小枚举
17         if(cnt[now][i]<0) continue;
18         if(solve(n,now+1,ls+cnt[now][i],k)){
19             num.push_back(i);
20             dp[now][ls]=1;
21             return 1;
22         }
23     }
24     dp[now][ls]=0;
25     return 0;
26 }
27 int main()
28 {
29     d[0][1]=1,d[0][2]=1,d[0][3]=1,d[0][5]=1,d[0][6]=1,d[0][7]=1;
30     d[1][3]=1,d[1][6]=1;
31     d[2][1]=1,d[2][3]=1,d[2][4]=1,d[2][5]=1,d[2][7]=1;
32     d[3][1]=1,d[3][3]=1,d[3][4]=1,d[3][6]=1,d[3][7]=1;
33     d[4][3]=1,d[4][4]=1,d[4][6]=1,d[4][2]=1;
34     d[5][1]=1,d[5][2]=1,d[5][4]=1,d[5][6]=1,d[5][7]=1;
35     d[6][1]=1,d[6][2]=1,d[6][4]=1,d[6][5]=1,d[6][6]=1,d[6][7]=1;
36     d[7][1]=1,d[7][3]=1,d[7][6]=1;
37     d[8][1]=1,d[8][2]=1,d[8][3]=1,d[8][4]=1,d[8][5]=1,d[8][6]=1,d[8][7]=1;
38     d[9][1]=1,d[9][2]=1,d[9][3]=1,d[9][4]=1,d[9][6]=1,d[9][7]=1;
39     int n,k;
40     scanf("%d%d",&n,&k);
41     for(int i=1;i<=n;i++){
42         scanf("%s",mp[i]+1);
43     }
44     //记忆化赋初值
45     for(int i=0;i<=2000;i++)
46     for(int j=0;j<=2000;j++){
47         dp[i][j]=-1;
48     }
49     //预处理过程
50     for(int i=1;i<=n;i++){
51         for(int j=0;j<=9;j++){
52             for(int z=1;z<=7;z++){
53                 if(d[j][z]==1&&mp[i][z]=='0'){
54                     cnt[i][j]++;
55                 }
56                 else if(d[j][z]==0&&mp[i][z]=='1'){
57                     cnt[i][j]=-inf;
58                 }
59             }
60         }
61     }
62     solve(n,1,0,k);
63     if(!num.size()) printf("-1\n");
64     else{
65         for(int i=num.size()-1;i>=0;i--){
66             printf("%d",num[i]);
67         }
68         printf("\n");
69     }
70     return 0;
71 }
View Code

 

   

posted @ 2020-05-15 11:46  古比  阅读(118)  评论(0编辑  收藏  举报