ZCMU - 1166: 忠哥的dp(II)

题目链接:点击打开链接

题目大意:略。

解题思路:完全背包。

AC 代码

#include<bits/stdc++.h>

#define mem(a,b) memset(a,b,sizeof a);

using namespace std;

typedef long long ll;

const int maxn=10000+10;
int dp1[maxn],dp2[maxn];
int weight[maxn];

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0;i<n;i++) scanf("%d",&weight[i]);
        for(int i=0;i<maxn;i++)
        {
            dp1[i]=maxn;
            dp2[i]=-maxn;
        }
        dp1[0]=dp2[0]=0;

        for(int i=0;i<n;i++)
        {
            for(int j=weight[i];j<=m;j++)
            {
                // PS1:加判断状态是否可转移(dp[m]一定代表正好背包放满的状态的值):因为for_j循环体内,每一种可能,都要经过判断,当前状态是否可转移,若可以,则调用max,否则跳过当前状态,进入下一种状态。
                // PS2:不加判断状态是否可转移(dp[m]不一定代表正好背包放满的状态的值):因为 j 代表每一种可能性,并不代表一个确定的使用空间的量,所以 dp[m] 到最后可能是一个虚值,但是如果dp初始化时,是个负大值(注意:这个负数要足够大,使虚值到达不了正数,否则会与真值混乱),dp[m] 最终且大于0,则该 dp[m] 是真实值。
                if(j==weight[i] || dp1[j-weight[i]]!=maxn)
                    dp1[j]=min(dp1[j],dp1[j-weight[i]]+1);
                if(j==weight[i] || dp2[j-weight[i]]!=-maxn)
                    dp2[j]=max(dp2[j],dp2[j-weight[i]]+1);
            }
        }

        printf(dp1[m]==maxn?"-1":"%d",dp1[m]);
        printf(dp2[m]<=0?" -1\n":" %d\n",dp2[m]); // 临界点是 dp2[m]>0 而不是 dp2[m]==-maxn

//        if(dp2[m]>0) // 因为最大值有符合的值,那么最小值肯定有,大不了最小值==最大值
//			printf("%d %d\n",dp1[m],dp2[m]);
//		else // 最大值都小于等于0,那么最小值肯定也没有
//			printf("-1 -1\n");
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

陆氪和他的那些代码

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

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

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

打赏作者

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

抵扣说明:

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

余额充值