題目鏈接
題意:這裏一定要吐槽一下這場完全是個閱讀理解題,這道題讀了半天才讀懂,非常的不友好,體驗感極差。
給你n個數位板,每個數位板由 7 個燈管組成給定 n 個數位板此時的狀態,1 爲亮 0 爲暗,要求嚴格再點亮 k 個燈管(注意必須剛好爲k,多一個少一個都不行),使得數位板上能夠呈現出數字,且這個數字最大,如果無法呈現出數字,輸出 -1,否則,輸出操作後呈現的數字。
思路:比賽的時候是靠爆搜過的,但這裏還是跟着大佬學習一下動態規劃的方法
,num【i】【j】代表第i個數位板變成數字j的所需要的燈管數。dp【i】【j】代表第i個板到第n個板使用了j個燈管能否構成數字,顯然我們最後要看的就是dp【1】【k】是否爲true,轉移方程爲dp【i】【j】|=dp【i+1】【j-num【i】【j】】,最後貪心的選擇數字大的就行了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2005;
string s[10]={"1110111", "0010010", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011"};
int n,k,num[maxn][10],ans[maxn];
bool dp[maxn][maxn];//dp[i][j]代表第i塊板到第n塊板剛好用了j個管子能否構成數字
int main()
{
string str;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)
{
cin>>str;
for(int j=0;j<10;++j)
{
for(int m=0;m<8;++m)
{
if(str[m]=='0'&&s[j][m]=='1') num[i][j]++;
else if(str[m]=='1'&&s[j][m]=='0') {num[i][j]=-1;break;}
}
}
}
memset(dp,false,sizeof(dp));
dp[n+1][0]=true;
for(int i=n;i>=1;--i)
for(int j=0;j<10;++j)
{
if(num[i][j]==-1) continue;
for(int m=num[i][j];m<=k;++m) dp[i][m]|=dp[i+1][m-num[i][j]];
}
if(!dp[1][k]) {
puts("-1");return 0;
}
for(int i=1;i<=n;++i)
{
for(int j=9;j>=0;--j)
{
if(num[i][j]==-1) continue;
if(k>=num[i][j]&&dp[i+1][k-num[i][j]])
{
ans[i]=j;
k-=num[i][j];
break;
}
}
}
for(int i=1;i<=n;++i) printf("%d",ans[i]);
}