一塊電子屏幕上有n個數字。c++
每一個數字是經過這樣7個線段顯示的,如今你不當心打壞了k個線段,給出打壞以後的n個數字的顯示方式,問以前的屏幕表示的最大數字是多少?spa
看數據範圍感受就是DP。3d
咱們把n個數字先倒過來,要儘量的讓後面的數字大。code
dp[i][j][k]
表示前i個數字打壞了j個線段最後一個數字爲k是否可行。blog
對於第i個數字,枚舉能夠變成的數字。get
回溯一下便可。博客
#include<bits/stdc++.h> #define pb push_back using namespace std; typedef long long ll; const int N=2e5+10; const int mod=1e9+7; const int inf=0x3f3f3f3f; char str[N][10]; char num[10][10]= {"1110111", "0010010", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011"}; int dp[2010][2010][10]; int main() { int n,k; scanf("%d%d",&n,&k); for(int i=n; i>=1; i--)//先把n個數字倒過來 scanf("%s",str[i]); for(int i=0; i<10; i++) dp[0][0][i]=1; for(int i=1; i<=n; i++)//前i個數字 { for(int j=0; j<=k; j++)//打壞了j個線段 { for(int l=0; l<=9; l++)//第i個數字爲l是否可行 { int flag=0,sum=0;//分別表示是否能夠變成l,以及須要的線段數量 for(int m=0; m<7; m++) { if(num[l][m]<str[i][m]) { flag=1; break; } sum+=num[l][m]-str[i][m]; } if(flag||j<sum) continue;//不能變成,或者須要的線段數量比打壞的多 for(int m=0; m<10; m++)//判斷當前是否可行 { if(dp[i-1][j-sum][m]) { dp[i][j][l]=1; break; } } } } } int sign=0; for(int i=0;i<=9;i++) { if(dp[n][k][i]) { sign=1; break; } } if(sign) { for(int i=n;i;i--) { for(int j=9;j>=0;j--)//每一位選擇最大的一個 { if(dp[i][k][j]) { printf("%d",j); for(int l=0;l<7;l++) k-=num[j][l]-str[i][l]; break; } } } printf("\n"); } else printf("-1\n"); return 0; }
博客it