码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu P1858 多人背包

时间:2019-10-21 21:01:55      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:背包   答案   scan   none   题解   clu   临时   efi   display   

gate

求01背包前k优解的价值和(题面还挺亲切的)

本来我想的是直接边跑01背包边记录,最后排序...

然后意识到,这种方法是枚举不全的。

看了眼题解...要多开一维!

k的范围很小,f[i][j]表示空间为i,是第j优解。

那么,因为有许多j,所以对于每个不一样的j,

f[i][j]既可能从f[i-c][...]+w转移过来,也可能从f[i][...]转移过来。

用类似于归并排序的方法:

维护两个指针t1,t2;

同时为了防止新的f覆盖原来的影响后续的状态转移,用一个临时的g[]记录,最后再转移过去。

那么就有g[t] = max(f[j-c][t1++]+w,f[j][t2++])

最后答案统计f[m][1-k]就可以了。

 

代码如下

技术图片
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
#define Darcy amour
using namespace std;

const int maxn = 1e5+10;
const int INF = 0x3f3f3f3f;
int k,m,n,c,w,ans,f[maxn][60],g[60];

int main() {
    scanf("%d%d%d",&k,&m,&n);
    memset(f,-INF,sizeof(f));
    f[0][1] = 0;
    for(int i = 1; i <= n; i++) {
        scanf("%d%d",&c,&w);
        for(int j = m; j >= c; j--) {
            int t1 = 1,t2 = 1;
            for(int t = 1; t <= k; t++) {
                if(f[j-c][t1] + w > f[j][t2])
                    g[t] = f[j-c][t1++] + w;
                else
                    g[t] = f[j][t2++];
            }
            for(int t = 1; t <= k; t++)
                f[j][t] = g[t];

        }
    }
    for(int i = 1; i <= k; i++)
        ans += f[m][i];
    printf("%d",ans);
    return 0;
}
View Code

 

 

Luogu P1858 多人背包

标签:背包   答案   scan   none   题解   clu   临时   efi   display   

原文地址:https://www.cnblogs.com/mogeko/p/11715703.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!