Programming Challenges 习题11.6.1

PC/UVa:111101/10131

Is Bigger Smarter?

输入一堆大象的体重和智商,求选出若干个大象,体重严格增加,智商严格递减。

从这章的讲解中学到了动态规划求具体解可以使用递归的方式,详见代码中的printSequence()

一道最长上升子序列的题目,另外这样的上升子序列多了一个智商的限制条件,并且可以改变输入的顺序,那就需要先根据体重排序(体重相同智商可以不排序,因为要求输入结果体重严格递增),然后再计算。

之前一直没有想明白,这种题为什么要把状态定义为以每个元素为结尾的最大序列长度。

根据无后效性的原则,假如已经通过i个数算出来了一些值,那么对于第i + 1个数,它要利用前面的结果。为了跟前面的数产生关系,那就依次将它排在前i个数每一个的后面,如果这两个数满足上升的关系,那么这两个数就构成了一个上升序列,那么以这个数为结尾的序列长度就和前面的数为结尾的序列长度产生了关系,所以状态就是以这个数为结尾的序列长度。

还有更重要的一点是,依次加入每一个数,好像也算不出来什么别的结果了。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct Elephant
{
	int weight, IQ;
	size_t No;
};

bool operator<(const Elephant &e1, const Elephant &e2)
{
	if (e1.weight < e2.weight) return true;
	else if (e1.weight > e2.weight) return false;
	else{
		if (e1.IQ > e2.IQ) return true;
		if (e1.IQ < e2.IQ) return false;
		else{
			return e1.No < e2.No;
		}
	}
}

void printSequence(const vector<Elephant> &vecElephant,
	const vector<int> &viParent, const int curr)
{
	if (viParent[curr] != -1){
		printSequence(vecElephant, viParent, viParent[curr]);
	}
	cout << vecElephant[curr].No << endl;
}

void LIS(const vector<Elephant> &vecElephant)
{
	vector<int> viLength(vecElephant.size(), 1);
	vector<int> viParent(vecElephant.size(), -1);
	for (size_t curr = 1; curr < vecElephant.size(); curr++)
	{
		for (size_t elephant = 0; elephant < curr; elephant++)
		{
			if (vecElephant[curr].weight > vecElephant[elephant].weight &&
				vecElephant[curr].IQ < vecElephant[elephant].IQ){
				if (viLength[elephant] + 1 > viLength[curr]){
					viLength[curr] = viLength[elephant] + 1;
					viParent[curr] = elephant;
				}
			}
		}
	}
	int maxLen = 0, maxLenIdx;
	for (size_t idx = 0; idx < viLength.size(); idx++)
	{
		if (viLength[idx] > maxLen){
			maxLen = viLength[idx];
			maxLenIdx = idx;
		}
	}
	cout << maxLen << endl;
	printSequence(vecElephant, viParent, maxLenIdx);
}

int main()
{
	vector<Elephant> vecElephant;
	Elephant elephant;
	while (cin >> elephant.weight >> elephant.IQ){
		elephant.No = vecElephant.size() + 1;
		vecElephant.push_back(elephant);
	}
	sort(vecElephant.begin(), vecElephant.end());
	LIS(vecElephant);
	return 0;
}
/*
6008 1300
6000 2100
500 2000
1000 4000
1100 3000
6000 2000
8000 1400
6000 1200
2000 1900
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值