F - Erase Subarrays(DP)[AtCoder Beginner Contest 275]

该博客主要介绍了动态规划在解决求解最优解问题中的应用,具体到一个选择数字使其和不超过给定限制的题目。通过DP[i][j][0/1]的状态转移方程,解释了如何在前i个数字中选择使得和为j,并考虑是否选取第i个数字。博客提供了完整的AC代码实现,并在最后输出可能的解。
摘要由CSDN通过智能技术生成

题目如下:

在这里插入图片描述
题目链接

思路 or 题解

D P [ i ] [ j ] [ 0 / 1 ] DP[i][j][0/1] DP[i][j][0/1]
在 前   i   个 数 字 中 选 择 , 和 为   j 在前\ i\ 个数字中选择,和为\ j  i  j
0   表 示   i   这 个 数 字 不 选 , 1   表 示   i   这 个 数 字 被 选 0\ 表示\ i\ 这个数字不选, 1\ 表示\ i \ 这个数字被选 0  i 1  i 

状态转移:
d p [ i ] [ j ] [ 0 ] = m i n ( d p [ i − 1 ] [ j ] [ 0 ] , d p [ i − 1 ] [ j ] [ 1 ] + 1 ) dp[i][j][0] = min(dp[i - 1][j][0], dp[i - 1][j][1] + 1) dp[i][j][0]=min(dp[i1][j][0],dp[i1][j][1]+1)
d p [ i ] [ j ] [ 1 ] = m i n ( d p [ i − 1 ] [ j − s [ i ] ] [ 0 ] , d p [ i − 1 ] [ j − s [ i ] ] [ 1 ] )     ( j − s [ i ] > = 0 ) dp[i][j][1] = min(dp[i - 1][j - s[i]][0], dp[i - 1][j - s[i]][1])\ \ \ (j - s[i] >= 0) dp[i][j][1]=min(dp[i1][js[i]][0],dp[i1][js[i]][1])   (js[i]>=0)
初试状态定义:
d p [ 0 ] [ 0 ] [ 1 ] = 0 dp[0][0][1] = 0 dp[0][0][1]=0
其余状态初试为:0x3f3f3f3f

AC代码:

int n, m, dp[N][N][2];
int s[N];
void solve()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> s[i];
    memset(dp, 0x3f, sizeof dp);
    dp[0][0][1] = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= m; j++)
        {
            if (j - s[i] >= 0)
                dp[i][j][1] = min(dp[i - 1][j - s[i]][0], dp[i - 1][j - s[i]][1]);
            dp[i][j][0] = min(dp[i - 1][j][0], dp[i - 1][j][1] + 1);
        }
    }

    for (int i = 1; i <= m; i++)
    {
        int ans = min(dp[n][i][0], dp[n][i][1]);
        if (ans == 0x3f3f3f3f)   ans = -1;
        cout << ans << '\n';
    }
}
int main()
{
    buff;
    solve();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Joanh_Lan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值