hdu2639——Bone Collector II——————【01背包、第k优解】
2015-01-27 17:05
197 查看
/**
解题思路:由于是让求第k优解问题,所以这里不再用转移方程,而是将转移过程转化成加入该件物品形成的有序序列tmpa[]和不加入该件物品形成的有序序列tmpb[]合并的过程。引用看到的一个例子:”如果想在全校找前十名的学生,只需要将各班的前十名合并后找前十即可“。
*/
/**
题目大意:给你t组测试数据,每组测试数据包含n,v,k。然后是两行分别代表第i件物品的价值和耗费,问第k大的值是多少。
*/
第一种处理方法:
第二种处理方法:
解题思路:由于是让求第k优解问题,所以这里不再用转移方程,而是将转移过程转化成加入该件物品形成的有序序列tmpa[]和不加入该件物品形成的有序序列tmpb[]合并的过程。引用看到的一个例子:”如果想在全校找前十名的学生,只需要将各班的前十名合并后找前十即可“。
*/
/**
题目大意:给你t组测试数据,每组测试数据包含n,v,k。然后是两行分别代表第i件物品的价值和耗费,问第k大的值是多少。
*/
第一种处理方法:
/** 第k优解问题:区别于dp求最大最小值,这种问题,需要再 加入一维坐标dp[i][k]表示背包容量为i时第k优解的值。 */ #include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int MAXN=110; int value[MAXN],volume[MAXN],dp[MAXN*10][MAXN],tmpa[MAXN*10],tmpb[MAXN*10]; int V,K; void Zero_One_Pack(int cost,int weight){ for(int i=V;i>=cost;i--){ for(int j=1;j<=K;j++){ //用两个临时数组分别记录新的物品加入背包或不加的前k项优解 tmpa[j]=dp[i][j]; tmpb[j]=dp[i-cost][j]+weight; } int x,y,z; // tmpa[K+1]=tmpb[K+1]=-1; x=y=z=1; while(z<=K&&(x<=K||y<=K)){ //循环,如果还没找到不同的第k优解或者两个临时数组还没比较完 // cout<<"z="<<z<<" x="<<x<<" y="<<y<<endl; // cout<<tmpa[x]<<" "<<tmpb[y]<<endl; // getchar(); //因为开始的时候给dp赋值为0,所以b数组的值在加入第一件物品 //时,值一定大于等于a数组中的值,所以这里不能加=,否则y会一直变 //大,而x却一般不会超过给定的k,发生错乱。 if(tmpa[x]<tmpb[y]){ //如果优解在b临时变量中,让优解赋给dp数组同时位置标志向后移动 dp[i][z]=tmpb[y]; y++; } else{ //同上 dp[i][z]=tmpa[x]; x++; } if(dp[i][z]!=dp[i][z-1]){ //过滤掉优解值相同的数 z++; } } } } int main(){ int t,n; cin>>t; while(t--){ memset(dp,0,sizeof(dp)); memset(tmpa,0,sizeof(tmpa)); memset(tmpb,0,sizeof(tmpb)); cin>>n>>V>>K; for(int i=0;i<n;i++){ cin>>value[i]; } for(int i=0;i<n;i++){ cin>>volume[i]; } for(int i=0;i<n;i++){ Zero_One_Pack(volume[i],value[i]); } cout<<dp[V][K]<<endl; } return 0; }
第二种处理方法:
/** 第k优解问题:区别于dp求最大最小值,这种问题,需要再 加入一维坐标dp[i][k]表示背包容量为i时第k优解的值。 */ #include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int MAXN=110; int value[MAXN],volume[MAXN],dp[MAXN*10][MAXN],tmpa[MAXN*10],tmpb[MAXN*10]; int V,K; void Zero_One_Pack(int cost,int weight){ for(int i=V;i>=cost;i--){ for(int j=1;j<=K;j++){ //用两个临时数组分别记录新的物品加入背包或不加的前k项优解 tmpa[j]=dp[i][j]; tmpb[j]=dp[i-cost][j]+weight; } int x,y,z; tmpa[K+1]=tmpb[K+1]=-1; x=y=z=1; while(z<=K&&(x<=K||y<=K)){ //循环,如果还没找到不同的第k优解或者两个临时数组还没比较完 // cout<<"z="<<z<<" x="<<x<<" y="<<y<<endl; // cout<<tmpa[x]<<" "<<tmpb[y]<<endl; // getchar(); //因为开始的时候给dp赋值为0,所以b数组的值在加入第一件物品 //时,值一定大于等于a数组中的值,所以这里不能加=,否则y会一直变 //大,而x却一般不会超过给定的k,发生错乱。但是如果将tmp[K+1]赋值 //为-1,可以避免出现y值停不下来而x值不变的情况。 if(tmpa[x]<=tmpb[y]){ //如果优解在b临时变量中,让优解赋给dp数组同时位置标志向后移动 dp[i][z]=tmpb[y]; y++; } else{ //同上 dp[i][z]=tmpa[x]; x++; } if(dp[i][z]!=dp[i][z-1]){ //过滤掉优解值相同的数 z++; } } } } int main(){ int t,n; cin>>t; while(t--){ memset(dp,0,sizeof(dp)); memset(tmpa,0,sizeof(tmpa)); memset(tmpb,0,sizeof(tmpb)); cin>>n>>V>>K; for(int i=0;i<n;i++){ cin>>value[i]; } for(int i=0;i<n;i++){ cin>>volume[i]; } for(int i=0;i<n;i++){ Zero_One_Pack(volume[i],value[i]); } cout<<dp[V][K]<<endl; } return 0; }
相关文章推荐
- Bone Collector II HDU - 2639 01背包,第k优解
- hdu 2639 Bone Collector II(求第k优解 01背包)
- hdu 01背包 2639Bone Collector II 01背包的第K优解
- dp之01背包hdu2639(第k优解)
- Hduoj2639【01背包+第k优解】
- 杭电 2639 Bone Collector II【01背包第k优解】
- hdu 2636 Bone Collector II 01背包(第k优解问题)
- hdu2639 bone collector II 01背包第k优解 TWT Tokyo Olympic 1COMBO-1
- 01背包 第k优解
- HDU 2639 Bone Collector II 【01背包的第k优解】
- hdu 2639 Bone Collector II (01背包,第k优解问题)
- hdu 2639 Bone Collector II(01背包)(第k优解)
- 【01背包求第K优解】HDU 2639 Bone Collector II
- HDU 2639 背包第k优解
- hdu 2639 次优解、第K优解 0-1背包
- hdu 2639 01背包的 第K优解
- hdu 2639 Bone Collector II(01背包的第k值)
- hdu 2639 Bone Collector II(01背包 第K大价值)
- 关于01背包求第k优解
- HDOJ2639(01背包第k最优解模板题)