codeforces Nastya and Scoreboard(dp)

本文介绍了一种使用动态规划(DP)解决火柴棍构造最大数字的问题算法。通过预先计算0到9每个数字由火柴棍组成的数量,然后采用逆向DP策略,从最后一组数字开始,逐步向前推导所有可能的状态,最终实现贪心策略来找到添加特定数量火柴棍后能构成的最大数值。文章详细展示了算法流程与核心代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:0~9每个数字由不同数量位置的火柴棍组成,一共n组数字,让你添加k根火柴棍,使n组数字可以构造的最大的数。若不能构成任何数,那么输出 -1

dp[i][j] 第i个数时,还剩下j个火柴棍,dp[i][j] = 1代表这个状态是可以构成的。那么初始值 dp[n+1][0] = 1代表 n+1个数时,剩下0个火柴棍的状态是1。从后往前推可以达到的状态,最后从前往后贪心得到结果。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define ff(i,a,b) for(int i = a; i <= b; i++)
#define f(i,a,b) for(int i = a; i < b; i++)
typedef pair<int,int> P;
#define ll long long


string num[10],s[2010];
int a[2010][10],sum[2010],dp[2010][2010];

int solve(int x, int y)
{
	int numm = 0;
	ff(i,0,6)
	{
		if(s[x][i] == '1' && num[y][i] == '0') return 1e9;
		else if(s[x][i] == '0' && num[y][i] == '1') numm++;
	}
	return numm;
}

int main()
{
    ios::sync_with_stdio(false);
    num[0] = "1110111";num[1] = "0010010";
    num[2] = "1011101";num[3] = "1011011";
    num[4] = "0111010";num[5] = "1101011";
    num[6] = "1101111";
    num[7] = "1010010";
    num[8] = "1111111";
    num[9] = "1111011";
    int n,k;
    cin >> n >> k;
    ff(i,1,n)
    {
    	cin >> s[i];
    	ff(j,0,9)
    	a[i][j] = solve(i,j);
    }
    memset(dp,0,sizeof(dp));
    dp[n+1][0] = 1;
    for(int i = n; i >= 1; i--)
    {
    	for(int kk = 0; kk <= 9; kk++)
    	for(int j = k; j >= a[i][kk]; j--)
    	{
    		dp[i][j] |= dp[i + 1][j - a[i][kk]];
    	}
    }
    string ans;
    int now = k,flag;
    ff(i,1,n)
    {
    	flag = 0;
    	for(int j = 9; j >= 0; j--) if(now >= a[i][j] && dp[i + 1][now - a[i][j]]) { now = now - a[i][j];ans += '0' + j; flag = 1; break;}
    	if(!flag) break;
    }
    if(!flag) puts("-1");
    else cout << ans << endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值