背包问题-Bone Collector II

本文介绍了一种解决背包问题中寻找第K大的解决方案的方法。通过递归过程中的两个数组记录选择与不选择物品的状态,并仅保留前K个最优解进行比较。此方法简化了问题并提高了效率。

这是一道求背包问题第k次大解。思路稍有点变法,就是在递归的过程中,分别用两个数组记录两种状态(选择或不选择),并且只要记录前k次。在这两个数组中都是前k次可能的最优解。所以我们只要把这两个数组做比较,一直排到k就行了,另外,对于递归问题,我们只要抓住某个状态的前后关系,把复杂问题简单化,不必去纠结全过程的状态,应为程序在运行时,递归过程是用堆栈实现的,其变化复杂,没必要每步弄懂。重点在于抓住前后规律和设计思路就可以了。


#include<stdio.h>
#include<string.h>

int dp[1001][50],wi[100],di[100];    
int n,m,k;

 void BK()
  {
    int a[50],b[50];           //用于记录当体积为j时,它的价值量。 
    int i,j,h;
    int x,y,z;
    for(i=0;i<n;i++)
     for(j=m;j>=wi[i];j--)
     {
       for(h=1;h<=k;h++)          //把前k个一次比较排序,不必要全部排完。 
         {
          a[h]=dp[j-wi[i]][h]+di[i];   //选择两次状态,应为它的优解,只可能在这两者选择。 
          b[h]=dp[j][h];               //要么选择一个,要么不选择。 
          }    
         x=y=z=1,a[h]=b[h]=-1;              //从两个数组中把前k的值排序,此时h>K,就不必管他了,令它为-1是应为 
        while(z<=k&&(a[x]!=-1||b[y]!=-1))  // 在选的时候,以保证x,y不会超出k范围。 
         {                                //这个循环就是从前k个里面选出最优解(降序)。 
            if(a[x]>b[y])
              dp[j][z]=a[x++];
            else
              dp[j][z]=b[y++];
            if(dp[j][z]!=dp[j][z-1])  
              z++;
         }
       }
     printf("%d\n",dp[m][k]);
}
                      
 int main()
  {   
    int t,i;
    scanf("%d",&t);
    while(t--)
     {
      scanf("%d%d%d",&n,&m,&k);
      for(i=0;i<n;i++)
       scanf("%d",&di[i]);
       for(i=0;i<n;i++)
       scanf("%d",&wi[i]);
       memset(dp,0,sizeof(dp));
       BK();
       }
       return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值