HDOJ 1160 FatMouse's Speed (子序列 - 动态规划)

题目:

FatMouse's Speed

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5546    Accepted Submission(s): 2393
Special Judge


Problem Description
FatMouse believes that the fatter a mouse is, the faster it runs. To disprove this, you want to take the data on a collection of mice and put as large a subset of this data as possible into a sequence so that the weights are increasing, but the speeds are decreasing.


 

Input
Input contains data for a bunch of mice, one mouse per line, terminated by end of file.

The data for a particular mouse will consist of a pair of integers: the first representing its size in grams and the second representing its speed in centimeters per second. Both integers are between 1 and 10000. The data in each test case will contain information for at most 1000 mice.

Two mice may have the same weight, the same speed, or even the same weight and speed.


 

Output
Your program should output a sequence of lines of data; the first line should contain a number n; the remaining n lines should each contain a single positive integer (each one representing a mouse). If these n integers are m[1], m[2],..., m[n] then it must be the case that

W[m[1]] < W[m[2]] < ... < W[m[n]]

and

S[m[1]] > S[m[2]] > ... > S[m[n]]

In order for the answer to be correct, n should be as large as possible.
All inequalities are strict: weights must be strictly increasing, and speeds must be strictly decreasing. There may be many correct outputs for a given input, your program only needs to find one.


 

Sample Input
  
  
6008 1300 6000 2100 500 2000 1000 4000 1100 3000 6000 2000 8000 1400 6000 1200 2000 1900


 

Sample Output
  
  
4 4 5 9 7
题目链接:
 

题意:

要求找到的体重递增,速度递减的老鼠,并且输出最长的长度数,而且输出各自的序列数。(Special Judge  说明答案不唯一,只要输出的答案正确就可以)

 

思路:

题目要求找到的体重递增,速度递减的老鼠,先把老鼠的体重进行升序排序,然后算出所给的数据序列的最长值,记录最长的序列要用father值来记录,path值则是来记录路径的,这两个是最重要的,另外还有注意题目是要求输入是以文件结束的,所以输入要想下面那样写,下面为图解(图的作用就是解释一下father和path的用法):

代码:(这是别人的代码,写得比较好,而且注释比较详细,所以就copy下来的)

/*
	
	老鼠跑步题 FatMouse's Speed 
	老鼠的体重和速度满足 体重越重,速度越慢 的最长序列
	
	题解:
		  对最长递增子序列的一个变形,要将两个决定元素转换为一个,所以先对老鼠
		  
			的体重从小到大排好序再对速度来求最长递减序列,反之也可。

	状态转移方程:

		max(  max(mouse[j].sp  |  j<i  && mouse[i].fa > mouse[j].fa && mouse[i].sp<mouse[j].sp )+1,  1); 

   这是最基础的动态规划,要很熟悉,然后学会变通!
	

  */



#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;


#define Max  150000


//动态规划的 打表数组 ; father[k]定义为:第k只老鼠排在子序列的第几位;
int father[Max];


//记录路径  path[k]定义为:第k只老鼠所在子序列的前一个满足要求的老鼠是;
int path[Max];  


//排序后老鼠序列和数组下标会有变化,注意index的理解和使用====记录path路径时候;
struct Node{

	int fa;
	int sp;
	int index; //记录是第几只老鼠  输入时的次序
	const bool operator < ( const Node old ) const{

		return fa<old.fa;
	}
};


Node mouse[Max];


int main(){

	int fat, spe;
	int n(1);

	//输入老鼠到文件末尾
	while(cin>>fat>>spe){
		mouse[n].fa=fat;
		mouse[n].sp=spe;
		mouse[n].index=n;
		n++;
	}

	//按体重排序;
	sort(mouse+1,mouse+n);

	int index(0);   //记录最大子序列的最后一个元素
	int max(-12122); //记录当前最
	int cut(0); 

	//初始化时所有的老鼠的路径只有自己,
	for(int kp(0);kp<=n;kp++){
		path[kp]=kp;
	}

	for(int i(1); i<n; i++){

		father[i]=1; // 动态方程 初始情况 

		//对当前老鼠前面所有老鼠中寻找满足条件,的max(   max(mouse[j].sp | j<i && mouse[i].sp<mouse[j].sp)+1,  1); 
		for(int j(1); j<i;j++){
			
			//对 fa 的判断必须要,因为要处理当体重相等时候 不可以进入判断;
			if(  mouse[i].fa > mouse[j].fa && mouse[i].sp < mouse[j].sp  &&  father[i]<father[j]+1){

				//更新i 在子序列中的位置
				father[i]= father[j]+1;

				//记录i 是接在 j 后面的 老鼠; 也可以看成: 第i 只老鼠被第j 只老鼠扩充;
				path[i]=j;

				// 记录最大的子序列个数,并保存序列长度 和 此时是哪只老鼠,
				if( father[i] >max ){
					max= father[i];
					index= i;
				}

			}
		}

	}
	cout<<max<<endl;
	stack<int> st;

	//获得子序列,--对应最短路径的输出路径 ---反向存储,用栈保存
	while(  path[index]!=index){
		st.push(mouse[index].index);
		index=path[index];
	}
	st.push(mouse[index].index);

	while( !st.empty()){
		cout<<st.top()<<endl;

		st.pop();
	}
 

	return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值