1. 程式人生 > >洛谷 P1858 多人背包 DP

洛谷 P1858 多人背包 DP

lse for bit 輸入輸出 輸入 pri 背包 toc turn

目錄

  • 題面
    • 題目鏈接
    • 題目描述
    • 輸入輸出格式
      • 輸入格式
      • 輸出格式
    • 輸入輸出樣例
      • 輸入樣例
      • 輸出樣例
    • 說明
  • 思路
  • AC代碼

題面

題目鏈接

洛谷 P1858 多人背包

題目描述

求01背包前k優解的價值和

輸入輸出格式

輸入格式

第一行三個數 $ K,V,N $

接下來每行兩個數,表示體積和價值

輸出格式

前 $ k $ 優解的價值和

輸入輸出樣例

輸入樣例

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

輸出樣例

57

說明

對於100%的數據, $ K \leq 50,V \leq 5000,N \leq 200 $

【時空限制】

1000ms,128MB

思路

求k優解。可以考慮開二維數組f[v][k],表示裝v體積物品的第k優解

加入每一件物品時,就要更新f[V]到f[v[i]]的值。對於新的f[v],應該是當前的f[v]與f[v-v[i]]+w[i]合並後的序列,取其中前k優就好了

AC代碼

#include<bits/stdc++.h>
const int maxk=60;
const int maxn=210;
const int maxv=5010;
using namespace std;

int k,V,n;
int v[maxn],w[maxn];
int f[maxv][maxk];
int ans;

int main()
{
    scanf("%d%d%d",&k,&V,&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&w[i]);
    for(int i=0;i<=V;i++)
        for(int j=0;j<=k;j++)
        f[i][j]=-100000;
    f[0][1]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=V;j>=v[i];j--)
        {
            int p1=1,p2=1,tmp[maxk];
            while(p1+p2-1<=k)
            {
                if(f[j][p1]>f[j-v[i]][p2]+w[i]) tmp[p1+p2-1]=f[j][p1],p1++;
                else tmp[p1+p2-1]=f[j-v[i]][p2]+w[i],p2++;
            }
            for(int t=1;t<=k;t++) f[j][t]=tmp[t];
        }
    }
    for(int t=1;t<=k;t++) ans+=f[V][t];
    printf("%d",ans);
    return 0;
}

洛谷 P1858 多人背包 DP