zoukankan      html  css  js  c++  java
  • Luogu P1858 多人背包

    P1858 多人背包

    题意

    题目描述

    (01)背包前(k)优解的价值和

    输入输出格式

    输入格式:

    第一行三个数(K)(V)(N)

    接下来每行两个数,表示体积和价值

    输出格式:

    (k)优解的价值和

    输入输出样例

    输入样例#1:

    2 10 5
    3 12
    7 20
    2 4
    5 6
    1 1
    

    输出样例#1:

    57
    

    说明

    对于(100\%)的数据,(Kleq 50,Vleq 5000,Nleq 200)

    思路

    让我先秒了这道水题。 --Mercury

    多重背包。考场上考到的时候使用的是(STL)中的优先队列求解,即对于每一个(V)状态开一个优先队列,更新时逐个取出再插入,超过(50)个时后面的不用再插回去了。

    这是一种显然的蚊子打高射炮高射炮打蚊子的做法,我们不妨这么想:

    对于一般的(01)背包问题,我们有标准的状态转移方程(f[i]=max(f[i],f[i-v[j]]+w[j])(igeq v[j]))。也就是说,对于每个物品而言,状态(f[i])只与(f[i])(f[i-v[j]])有关,所以我们不妨设计(f[i][j])表示(f[i])的第(j)优解,更新时因为(f[i][j])是有单调性的,所以拿单调指针从左往右扫一遍,扫出(k)个最优解,来更新就好了:

    for(int i=V;i>=v[j];i--)//01背包倒序枚举
    {
        int cnt=0,cfr=0,cto=0;//cnt记录更新后的解,cto记录更新前的解,cfr记录f[i-v[j]]的解
        while(cnt<k)//找到k个解
            if(f[i][cto]>f[i-v[j]][cfr]+w[j]) tmp[cnt++]=f[i][cto++];//扫描
            else tmp[cnt++]=f[i-v[j]][cfr++]+w[j];
        for(int w=0;w<k;w++) f[i][w]=tmp[w];//更新
    }
    

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    int k,v,n,ans,f[5005][55],tmp[55];
    int read()
    {
        int re=0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
        return re;
    }
    int main()
    {
        k=read(),v=read(),n=read();
        memset(f,0xcf,sizeof f);
        f[0][0]=0;
        while(n--)
        {
            int x=read(),y=read();
            for(int i=v;i>=x;i--)
            {
                int cnt=0,cfr=0,cto=0;
                while(cnt<k)
                    if(f[i][cto]>f[i-x][cfr]+y) tmp[cnt++]=f[i][cto++];
                    else tmp[cnt++]=f[i-x][cfr++]+y;
                for(int j=0;j<k;j++) f[i][j]=tmp[j];
            }
        }
        for(int i=0;i<k;i++) ans+=f[v][i];
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    01快速入门-03-条件判断和循环
    01快速入门-02-数组和对象
    01快速入门-01-基本语法和数据类型
    《Head First 设计模式》[01] 策略模式
    爬山算法与模拟退火算法的分析与实现
    Java虚拟机(二) —— 运行时数据区的OOM异常
    CoreJava(一)—— Java迭代语句
    Java虚拟机(二) —— 垃圾回收算法与垃圾回收器
    算法学习 —— 使用Linux C++练习OJ
    Java虚拟机(一) —— 运行时数据区
  • 原文地址:https://www.cnblogs.com/coder-Uranus/p/9811113.html
Copyright © 2011-2022 走看看