PC/UVa:111101/10131
输入一堆大象的体重和智商,求选出若干个大象,体重严格增加,智商严格递减。
从这章的讲解中学到了动态规划求具体解可以使用递归的方式,详见代码中的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
*/