ZOJ 1108(FatMouse's Speed)

//经典dp

//难点在于序列路径的输出(使用“前驱法”)

#include<iostream>
#include<algorithm>
using namespace std;
int dp[1001], pre[1001];
struct mice
{
	int order; //记住初始时各只老鼠的顺序,避免后面操作时打乱
	int weight;
	int speed;
}m[1001];

bool cmp(mice &m1, mice&m2) //这里不使用二级结构体排序也可以直接AC
{
	return (m1.weight < m2.weight);
}

void output(int i) //递归后,正向输出路径
{
	if (pre[i] == 0)
	{
		cout << m[i].order << endl;
		return;
	}
	output(pre[i]);
	cout << m[i].order << endl;
}
int main(void)
{
	//freopen("Text.txt", "r", stdin);
	int i = 1, total, ans = 0, ans_index;
	while (cin >> m[i].weight >> m[i].speed)
	{
		pre[i] = 0;
		//千万千万不要简写成  m[i].order=i++;,WA了一下午
		//之前自己写的第一个程序直接就AC了,后来看到别人用这个i++就学别人了,结果一直WA
		//,又不知道原因
		m[i].order = i;  
		i++;
	}
	total = i - 1;
	sort(m + 1, m + total + 1, cmp);
	for (int i = 1; i <= total; i++)
	{
		dp[i] = 1;
		for (int j = 1; j < i; j++)
		{
			if (m[j].speed > m[i].speed&&m[j].weight < m[i].weight&&(dp[i] < dp[j] + 1))
			{
				dp[i] = dp[j] + 1;
				pre[i] = j; //记录j的前驱是i,以利于后面路径的输出
			}
		}
		if (ans < dp[i])
		{
			ans = dp[i];
			ans_index = i;
		}	
	}
	cout << ans << endl;
	output(ans_index);
	return 0;
}

///



// 常规的路径输出方法,定义一个路径数组存储路径
include<iostream>
#include<algorithm>
using namespace std;
int dp[1001], pre[1001],route[1001];
struct mice
{
	int order;
	int weight;
	int speed;
}m[1001];

bool cmp(mice &m1, mice&m2)
{
	return (m1.weight < m2.weight);
}
int main(void)
{
	//freopen("Text.txt","r",stdin);
	int i = 1, total, ans = 0, ans_index;
	while (cin >> m[i].weight >> m[i].speed)
	{
		pre[i] = 0;
		m[i].order = i;
		i++;
	}
	total = i - 1;
	sort(m + 1, m + total + 1, cmp);
	for (int i = 1; i <= total; i++)
	{
		dp[i] = 1;
		for (int j = 1; j < i; j++)
		{
			if (m[j].speed > m[i].speed&&m[j].weight < m[i].weight && (dp[i] < dp[j] + 1))
			{
				dp[i] = dp[j] + 1;
				pre[i] = j;
			}
		}
		if (ans < dp[i])
		{
			ans = dp[i];
			ans_index = i;
		}
	}
	cout << ans << endl;
	//到这里已经知道路径数组的规模为ans
	int end = ans_index;
	for (int i = ans; i >= 1; --i) //这里反向存储,便于后面正向输出
	{
		route[i] = end;
		end = pre[end];
	}
	for (int i = 1; i <= ans; i++) cout << m[route[i]].order << endl;
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值