求01背包的第k大解
2013-04-14 16:40
134 查看
这是一道求背包问题第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; }
相关文章推荐
- nyoj--289--苹果(01背包)
- [算法]01背包问题
- nyoj 325 zb的生日 (dfs搜索)(01背包)
- 杭电ACM2546(01背包)
- hdu 2546 饭卡(01背包)
- dp重拾-01背包--HDU 2602
- 中级篇——背包问题1(01背包)
- hdu 2639 Bone Collector II(01背包)(第k优解)
- HDU-3466-Proud Merchants(01背包问题)
- HDU-1864-最大报销额【01背包】
- hdu5616Jam's balance(01背包或者折半搜素)(BestCoder Round #70 )
- hdu2602 Bone Collector(01背包+入门)
- HDU 2546 饭卡(01背包)
- Knapsack problem (FZU_2214,福建省第六届ACM-problemC) 01背包+初始化问题+渐缩问题
- Bone Collector II (HDU_2639) 01背包 + 第K优解
- UVA 562 分钱(01背包)
- hdu1864 (01背包)
- 【POJ3624】Charm Bracelet(01背包)
- 蓝桥杯_算法提高_01背包(动态规划算法)
- 杭电2955Robberies(01背包)