hdu 2639 (第k小的01背包)

题意:第k小的01背包,重复的选项算一个

分析:01背包问题,只考虑到第i个问题的各个体积的最优解,而第k大的01背包则需要更多的选项,有个博客举了这样一个例子

我们年纪一共10个班,如果我想知道年纪第一,我需要知道每个班级的第一名,一比较,那么我就知道年纪第一是谁了

如果我要知道年纪前十名,那么,我只要知道每个班的前10名,那么我比较之后就知道了年级的前十名

dp[i][j]表示体积为i时,价值为第j大的价值,每次选择物品的时候,计算出所有的体积,把前k名按照顺序插入到dp[i]中,这样,最后得到答案dp[n][v]

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+5;

int dp[maxn][35],v[105],w[105],A[35],B[35];

int main(){
    int n,V,t,k;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d",&n,&V,&k);
        for(int i=1;i<=n;i++)
            scanf("%d",v+i);
        for(int i=1;i<=n;i++)
            scanf("%d",w+i);
        memset(dp,0,sizeof(dp));

        int a,b,c,kk;

        for(int i=1;i<=n;i++)
            for(int j=V;j>=w[i];j--){
                for(kk=1;kk<=k;kk++){
                    A[kk]=dp[j][kk];
                    B[kk]=dp[j-w[i]][kk]+v[i];
                }
                A[kk]=B[kk]=-1;
                a=b=c=1;

                while(c<=k&&(A[a]!=-1||B[b]!=-1)){
                    if(A[a]>B[b])
                        dp[j][c]=A[a++];
                    else
                        dp[j][c]=B[b++];
                    if(dp[j][c]!=dp[j][c-1])
                        c++;
                }
            }
        printf("%d\n",dp[V][k]);
    }
    return 0;
}
View Code

 

posted @ 2016-02-28 20:03  N维解析几何  阅读(219)  评论(0编辑  收藏  举报