HDU - 2639 Bone Collector II 01背包的第K最优

原题:
骨头收集者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;
}


猜你喜欢

转载自blog.csdn.net/qq_26558047/article/details/85082368