FatMouse‘s Speed--最长单调递增子序列--动态规划

问题描述:
FatMouse相信:长得越胖的老鼠跑得越快。为了证明这是不对的,你需要搜集老鼠的数据。然后,在这些数据中选取一个尽可能大的子集,从而发现体重不断增长时,速度却不断下降。
输入
输入一群老鼠的资料,每只老鼠占一行。
每只老鼠的数据是一对整数:
第一个表示它的体重(克),第二个表示它的速度(厘米/秒),两个整数的范围是1~10000。
每组测试数据最多包含1000只老鼠的信息。
任何两只老鼠有可能体重相同,或速度相同,甚至体重和速度都完全相同。
输出
输出一系列数据;第一行是数字n;
接着有n行,每行是一个正整数(每个代表一只老鼠)。
如果这n个整数是m[1],m[2],…,m[n],则必须满足:
  W[m[1]]<W[m[2]]<…<W[m[n]]
和 S[m[1]]>S[m[2]]>…>S[m[n]]
为了确保答案是正确的,n应该尽可能的大。
所有的不等式都严格遵守约束:重量一定严格的逐渐增加,速度一定严格的逐渐减少。
可能有多种正确输出,你的程序只需输出其中一个:
本题为Special Judge。
在这里插入图片描述

算法分析:

  • 因为有两个序列方向,直接应用最长单调递增子序列算法是不行的。
  • 对数据进行预处理,首先按重量升序,重量相同时,按速度降序,然后对速度序列应用最长单调递增子序列算法

1、样例分析
按重量升序,重量相同时,按速度降序后的排列后的结果如下图。
在这里插入图片描述
可以看出满足要求的序列最大长度是4。
在序号5、6和7的位置,三个重量都是6000,只能取一个速度。
在长度为4的情况下,显然答案有多组,所以是Special Judge:
① 4,5,2,1
② 4,5,2,7
③ 4,5,6,1
④ 4,5,6,7
⑤ …
2、数据结构
采用结构体表示老鼠的资料:

struct mouse { 
	//老鼠的重量、速度和编号
	int weight, speed, id;	
} mice[1001]; 

老鼠的实际数量用变量n表示。
3、排序算法的实现
采用C语言的qsort()排序:

qsort(mice, n, sizeof(mouse), cmp);

其中cmp是排序因子。
在排序因子函数中,按老鼠的重量升序,在重量相同时,按速度降序。

//排序因子
int cmp(const void * a, const void * b)
{
 mouse* ta = (mouse*) a;
 mouse* tb = (mouse*) b;
 if(ta -> weight == tb -> weight)		//重量相同时
  return tb -> speed - ta -> speed;	//按速度降序
 return ta -> weight - tb -> weight;	//按重量升序
}

4、最长单调递增子序列算法的实现
实现时需要两个辅助数组:
① 存储构造到第i(1≤i<n)个老鼠时,序列的最大长度:

int count[1001] = {0};

在这里插入图片描述
②存储构造到第i(1≤i<n)个老鼠时,序列的前驱:

int path[1001] = {0};

在这里插入图片描述
在这里插入图片描述

//最长单调递增子序列算法
//下面是针对排序后的数组
int count[1001] = {0};		//序列的最大长度
int path[1001] = {0}; 		//序列的前驱
count[1] = 1;
for(int i = 2; i < n; i++)
{
 for(int j = 1; j<i; j++)
  if(mice[i].weight>mice[j].weight  && mice[i].speed<mice[j].speed)
   if(count[i] < count[j])		//得到了更长的序列
   {
    count[i] = count[j];
    path[i] = j;			//记录前驱
   }
 count[i]++;
}
//查找最大的序列长度
int max = 0;		//最大长度
int pos;		//最大长度元素所在位置
for(int i = 1; i < n; i++)
 if(count[i] > max)
 {
  max = count[i];
  pos = i;
 }
//输出最大长度
printf("%d\n", max);

在这里插入图片描述
5、输出子序列的序号
首先查找最大的序列长度,也就是在数组count中查找最大值max,并记录该最大值所在的位置pos。

  • 根据位置pos,在数组path中递归输出就可以了。
  • 如果当前位置是pos,则前一个位置是path[pos]。
  • 采用递归算法,刚好确保从前往后的顺序输出。
 
 //输出子序列序号的算法
void output(int path[], int pos)
{
 if(pos == 0) return;
 output(path, path[pos]);
 printf("%d\n", mice[pos].id);
}

在这里插入图片描述
在这里插入图片描述

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值