[HDU1160]-FatMouse's Speed

FatMouse's Speed

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 14574    Accepted Submission(s): 6435
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
题目描述:
给你少于1000行数据,每行两个数,第一个数值w是mouse的体重,第二个数值p是mouse的速度,要你求得满足
W[m[1]] < W[m[2]] < ... < W[m[n]] and  S[m[1]] > S[m[2]] > ... > S[m[n]]
条件的最大子序列,输出最大子序列的长度, 然后输出最大子序列的位置。
解题思路:
首先进行模型,可能咋看此题有点怪异,只要进行处理下(按照w或者p进行排序),就变成了最长上升子序列模型,
然后需要记 录路径,求最长上 升子序列的的方法较多, 但是由于这里需要的记录路径,所以,还是选择DP 为上策,
不然可能难处理,清华大学 出版社出版的《程序设计引导以及在线》 这本书,上面就有这样的模板DP方法做最长上
序列,由于需要进行路径的记录,所以 需要一个数组来存储路径,这个处理是解此题的关键点,我们 可以这样进行
处理: 先定义一个标记数组vis[maxn],并对其进行初始化,vis[i]=i; 如果一个数列他的 1 3 5 6 9 为它的
最长上升子序列, 那么我们可以用vis数组这样处理,每次将vis[now]=pre, 就像现在这种情况
vis[3]=1; vis[5]=3 ;vis[6]=5; vis[9]=6;
这样只要获得最长上升子序列的位置终点位置,就能获得所有的路径,就像上面的example,只要我获得9那
么我就能获得 全部路径,code和注解如下
<span style="color:#cc6600;">#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 10002;
int dp[maxn];
int vis[maxn];
int aMaxLen[maxn];
int flag;//标记
int tmp;
int cnt=0;
int nMax = -1;//获得最大长度
int rem[maxn];
int p=0;
struct animals
{
	int weight,speed;
	int pos;
}mouse[maxn];
bool cmp(animals mouseA,animals mouseB)
{
	if(mouseA.weight==mouseB.weight)
		return mouseA.speed < mouseB.speed;
	return mouseA.weight > mouseB.weight;
}
void init()
{
	p=0;
	memset(mouse,0,sizeof(mouse));
	memset(dp,0,sizeof(dp));
	for(int i = 1;i < maxn;++ i)
		vis[i]=i;
	return;
}
void debug_print()
{
	for(int i = 0;i < cnt;++ i)
		cout << mouse[i].pos<<" ";
	cout << endl;
}
void debug_print_vis()
{
	for(int i = 0;i < cnt;++ i)
		cout << vis[i] << " ";
	cout << endl;
}
int main()
{
	freopen("data1160.in","r",stdin);
	ios::sync_with_stdio(false);
	init();
	for(cnt = 1;cin>>mouse[cnt].weight>>mouse[cnt].speed;++ cnt)
		mouse[cnt].pos=cnt;
	sort(mouse+1,mouse+cnt,cmp);
	// debug_print();
	for(int i = 1;i < cnt;++ i)//每次求以第i个数为终点的最长上升子序列的长度
	{
		int nTmp=0;//记录满足条件的,第i个数左边的上升子序列的最大长度
		for(int j = 1;j < i;++ j)
		{
			if(mouse[i].weight<mouse[j].weight&&mouse[i].speed>mouse[j].speed)
			{
				if(nTmp<dp[j])
				{
					nTmp = dp[j];
					flag = mouse[j].pos;//标记此位置-------------------------------(oo)
				}
			}
			if(nTmp)//如果能找到满足条件的进行标记
			{
				/*用vis数组存储下来,理解这个是最关键的,我们从上面的oo位置可以知道flag是查询i之前的最大上升子序列的位置
				此时,把i节点的位置和j节点的位置连接起来,形成一种链状形式,那么只要我得到最长链的端点就能查找到所有点的位置了*/
				vis[mouse[i].pos]=flag;
				// cout << "flag:" << flag << endl;
				// debug_print_vis();
			}
			dp[i]=nTmp+1;
		}
		if(nMax < dp[i])
		{
			nMax = dp[i];//获得最大长度
			/*获得最后最长上升子序列的终点位置,此点就是我们上面描述的最长链的端点*/
			tmp = mouse[i].pos;
			// cout << "tmp:" << tmp << endl;
		}
	}
	cout << nMax << endl;
	while(tmp!=vis[tmp])
	{
		cout << tmp << endl;
		tmp = vis[tmp];
	}
	cout << tmp << endl;
	return 0;
}</span>


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值