zoukankan      html  css  js  c++  java
  • hdu(2639)(01背包的第k最优解)

     该题目为求01背包中的第k最优解:
     开始时用dpp[i][j]表示用体积为i得到价值为j,WA了好多次,系统说是数组开的大小有问题
     应该定义数组dp[i][j][k]表示前i个物品中用体积j所得价值排名第k,类似于dp[i][j],
     该数组每次有两个方案可得,即dp[i-1][j][k]与dp[i-1][j-cost[i]][k]+value[i];
     用数组A及数组B分别保存数组dp[i-1][j][k]及数组dp[i-1][j-cost[i]][k]+value[i]的前k项,
     再对两个数组进行合并,赋值给dp[i][j][k],不过知道最优是k优的一种特殊情况了,代码如下:
    #include <iostream>
    #include <cstdio>
    #include <string.h>
    int dp[1005][35],value[1005],volume[1005],A[35],B[35];
    int main()
    {
        int t,n,i,j,k,v,kk,a,b,c;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&v,&k);
            for (i=1;i<=n;++i)
            scanf("%d",&value[i]);
            for (i=1;i<=n;++i)
            scanf("%d",&volume[i]);
            memset(dp,0,sizeof(dp));
            for (i=1;i<=n;++i)
            for (j=v;j>=volume[i];--j)
            {
                for (kk=1;kk<=k;++kk)
                {
                    A[kk]=dp[j-volume[i]][kk]+value[i];//分类取前K大
                    B[kk]=dp[j][kk];
                }
                a=b=c=1;
                while(c<=k&&(a<=k||b<=k))//a<=k||b<=k表示还有没有取完的,该循环是对两个数组进行合并
                {
                    if (A[a]>B[b])
                    dp[j][c]=A[a],a++;
                    else
                    dp[j][c]=B[b],b++;
                    if (dp[j][c]!=dp[j][c-1])//即前后不相等,由前两个if判断条件可知dp数组以一定的顺序保存了
                    ++c;
                }
            }
            printf ("%d\n",dp[v][k]);
        }
        return 0;
    }
    
  • 相关阅读:
    开不了的窗_____window.open
    IIS项目发布完整流程
    理解MVC模式
    ASP.NET MVC 基础(01)
    C#之线程和并发
    vue时间格式化
    windows 2013 datacenter 安装sql server2008 r2兼容性
    SQL Server DBA十大必备工具使生活轻松
    ORACLE主要的系统表和系统视图
    Oracle中spool命令实现的两种方法比较
  • 原文地址:https://www.cnblogs.com/1994two/p/3068697.html
Copyright © 2011-2022 走看看