原题:
骨头收集者2
题大意:
是在骨头收集者1的基础下,除了找到最优项,还要找到第K个最优项;
也就是说,不能把01背包的转换公式中的
max(xxxxxx,yyyyyy)两者选其一
而是要全部保留下来;
(这个是最重要的重点)
否则就会以为在01背包的二维表格基础上找到第k大的;
题目关键:
是要学会开多一维数组,而不是以a[][][]的形式;
事实上,开多一维(相当于在for里镶嵌多一个for)
for(i→N)→表示前i件物体放进背包的情况
for(j=V→hav[i])表示该hav[i]的起步下,一个背包容量逐步递增的情况
(以上是裸01背包问题)
for(t=1 → k) 表示该容量下的第k大价值;
三维数组;
一共多少个数据的表示;
以下是AC的代码:
#include "stdafx.h"
#include<iostream>
using namespace std;
int main()
{
int fa[1010][35]; //用来记录第K最优价值;
int a[35], b[35]; //用来暂时存第K最后价值;
int hav[110], val[110];
int text; //表示测试数据;
int N, V, K;
cin >> text;
while (text)
{
cin >> N >> V >> K;
for (int i = 0; i < N; i++) //输入价值;
{
cin >> val[i];
}
for (int i = 0; i < N; i++) //输入重量;
{
cin >> hav[i];
}
memset(fa, 0, sizeof(fa)); //初始化;
for (int i = 0; i < N; i++) //表示第几个物品;
{
for (int j = V; j >= hav[i]; j--) //表示对第i件物品,所有的可能价值;
{
for (int t = 1; t <= K; t++) //每一个j,都有有一个价值排序;表示第几大价值; (三维数组);
{
a[t] = fa[j][t];
b[t] = fa[j - hav[i]][t] + val[i];
}
int t = 1, x = 1, y = 1; //用t表示第几个大价值,x,y表示有a,b暂存的;
a[K + 1] = -1; //用来跳出;
b[K + 1] = -1;
while (t <= K && (a[x] != -1 || b[y] != -1)) //记得a和b数组不是相同的,b数组的第一个
{
if (a[x]>b[y])
{
fa[j][t] = a[x];
x++;
}
else
{
fa[j][t] = b[y];
y++;
}
if (fa[j][t] != fa[j][t - 1])
{
t++;
}
}
}
}
cout << fa[V][K] << endl;
text--;
}
return 0;
}