Codeforces 1132E(转化+dp)

要点

  • 假设第i个最后总共选的值为ci,不妨把它分成两部分:\[c_i=cnt'_i*L+q_i\]\[L=840,\ 0<=q_i<L\]又可以写成:\[c_i=cnt_1*i+cnt_2*i\]\[cnt_i'=\frac{cnt_1}{\frac{L}{i}},\ q_i=cnt_2*i\]所以\[maxcnt'_i=\frac{cnt[i]-cnt_2}{\frac{L}{i}}\]一会dp要用。
  • 事实上如果只有一个item的话,L取它的倍数即可;而8个数我们为了将它们合在一起算,所以取一个它们的LCM。这样做的目的是\[ans=L*\sum_{i=1}^8{cnt'_i}+\sum_{i=1}^8{q_i}\]而此时\[0<=q_i<=8*L\]这个值并不大,我们就可以dp做了。
  • 设dp[i][j]:在前i个数中取、全部的qi为j时,最多的cnt'。这样最后就既有qi又有cnt',可以直接算出答案。
  • 精简dfs做的大佬tql,学不来学不来……
const int N = 9;
const int L = 840;

ll W, cnt[N], dp[N][L * N];

int main() {
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    cin >> W;
    rep(i, 1, 8)    cin >> cnt[i];

    memset(dp, -1, sizeof dp);
    dp[0][0] = 0;
    rep(fakei, 0, 7) {
        rep(j, 0, L * fakei) {
            if (dp[fakei][j] >= 0) {
                int i = fakei + 1;
                rep(k, 0, min(cnt[i], (ll)(L / i))) {
                    dp[i][j + k * i] = max(dp[i][j + k * i], dp[fakei][j] + (cnt[i] - k) / (L / i));
                }
            }
        }
    }

    ll ans = 0;
    rep(j, 0, L * 8) {
        if (j > W)  break;
        if (dp[8][j] >= 0) {
            ans = max(ans, min(dp[8][j], (W - j) / L) * L + j);
        }
    }
    cout << ans << endl;
    return 0;
}

转载于:https://www.cnblogs.com/AlphaWA/p/10693019.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值