对于我的难点来讲是输出最长上升子序列(某一个),在这里用到了标记,用数组标记以当前数为结尾的最长上升子序列的前一个数,以我个人浅陋的见解,认为这是有记忆化搜索思想的。
/* fat mouse’s speed
* 1.降低维度,排序将重量维度消掉
* 2.输出最长的上升子序列长度,同时将上升子序列输出
* 这一点我个人认为用到了记忆化搜索,跟动态规划相关性不强
* (1).不知道哪一组数会成为最长的上升子序列,则将所有数据对应的上一个数据进行标记
* (2).最终利用已知的最后一只老鼠进行结果保存,同时保证正序输出
*/
#include<iostream>
#include<algorithm>
#include<string.h>
int index[1010];
int pos[1010];
int dp[1010];
using namespace std;
struct mouse
{
int weight;
int speed;
int num;
}a[1010];
bool cmp(mouse a, mouse b)
{
if (a.weight == b.weight)return a.speed > b.speed;
return a.weight < b.weight;
}
int main()
{
int i = 1,j;
//对于多循环来讲,早定义能够使代码简洁(小细节)
while (cin >> a[i].weight >> a[i].speed)
{
a[i].num = i;
index[i] = 0;
/* 帮助后面输出数组时能够终止
* 相应编号所指代的前一个数为0,则终止输出(终止条件)
*/
i++;
}
sort(a, a + i, cmp);
int ans = 1, maxi;
int n = i - 1;
//ans用来记录最大上升子序列个数
//end用来记录最后一个元素指代,从而能够用数组存储
for (i = 1; i <= n; i++)
{
dp[i] = 1;
for (j = 1; j < i; j++)
{
if (a[i].weight > a[j].weight && a[i].speed < a[j].speed&& dp[j] + 1 > dp[i])
{
dp[i] = dp[j] + 1;
index[i] = j;
//用来指代上一个元素,这样的话,每一个元素对应的上升部分都会被得到标记
//注意,最长上升部分需要利用状态转移方程标记,切记最长!
}
if (ans < dp[i])
{
ans = dp[i];
maxi = i;
//选取最后一个目标元素,也就是最大的那一个,这样,因为之前都被标记,所以能够输出
}
}
}
int t = maxi;
i = 0;
//想要按初始顺序输出的话再找一个数组存入
while(t)
{
pos[i++] = t;
//pos[i]++=index[t],我刚开始写成这个,找错误找了一天,无语
t = index[t];
}
cout << i << endl;
while(i>0)
{
i--;
cout << a[pos[i]].num << endl;
}
/* while(i-->0)
* 也可以改写成这样,充分利用i--的后效性
* 效果:1.在当时不进行减法,同时能够输出相应的-1元素
* 2.在最后一次,能够输出a[pos[0]].num且不终止循环
*/
}