Codeforces Round #637 (Div. 2) - Thanks, Ivan Belonogov! (Dp+貪心)(好題*)

題目鏈接
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
題意:這裏一定要吐槽一下這場完全是個閱讀理解題,這道題讀了半天才讀懂,非常的不友好,體驗感極差。
給你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]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章