OpenJudge NOI 2.1 8759:火车上的人数

【题目链接】

OpenJudge NOI 2.1 8759:火车上的人数

【题目考点】

1. 枚举

2. 递推

【解题思路】

设在第2站上车b人
列表找规律:

站点 上车人数(u) 下车人数(d) 从第i站出发时车上人数(p)
1 a 0 a
2 b b a
3 a+b b 2a
4 a+2b a+b 2a+b
5 2a+3b a+2b 3a+2b

记第i站上车人数为 u i u_i ui,下车人数为 d i d_i di,从第i站出发时车上人数为 p i p_i pi
题目所求的是在第x站出发时车上的人数,即 p x p_x px,实际就是要求p数组。

i ≥ 3 i\ge 3 i3时有规律:
u i = u i − 1 + u i − 2 u_i=u_{i-1}+u_{i-2} ui=ui1+ui2
d i = u i − 1 d_i=u_{i-1} di=ui1
p i = p i − 1 + u i − d i = p i − 1 + u i − 2 p_i=p_{i-1}+u_i-d_i=p_{i-1}+u_{i-2} pi=pi1+uidi=pi1+ui2
已知第n站下车m人,即第n-1站出发时车上有m人,即 p n − 1 = m p_{n-1} = m pn1=m

这里不方便得到以b为未知数的方程。如果用枚举算法来做的话,其实也不是一定要把方程列出来。
这里可以枚举b的值。
关于b的范围,最小为0。根据题目提供的条件,n最小值为4。

  • 当n为4时, m = p 3 = 2 a m=p_3=2a m=p3=2a,此时b的值不起作用,b可以在任意范围内枚举。
  • n > 4 n>4 n>4时,根据上述规律可以看出,一定有 m = p n − 1 > b m=p_{n-1} > b m=pn1>b

因此把b的最大值设为m-1即可。

  • 枚举对象:b
  • 枚举范围: 0 ≤ b ≤ m 0\le b \le m 0bm
  • 判断条件:
    已知 u 1 = a , u 2 = b u_1=a, u_2=b u1=a,u2=b,递推关系 u i = u i − 1 + u i − 2 u_i=u_{i-1}+u_{i-2} ui=ui1+ui2
    已知 p 2 = a p_2=a p2=a,递推关系 p i = p i − 1 + u i − 2 p_i=p_{i-1}+u_{i-2} pi=pi1+ui2
    递推求出 p n − 1 p_{n-1} pn1,判断是否满足 p n − 1 = m p_{n-1}=m pn1=m
    如果满足,则找到了解,输出 p x p_x px

复杂度分析:b循环m次,m最大为 1 0 4 10^4 104,递推最大循环接近n次,n最大为15,因此总循环次数为 1 0 4 ∗ 15 ≈ 1 0 5 10^4*15\approx10^5 10415105数量级,可以接受。

【题解代码】

解法1:枚举

#include <bits/stdc++.h>
using namespace std;
#define N 20
int main()
{
    
    
	int a, n, m, x, u[N], p[N];//u[i]:第i站上车的人数 p[i]:第i站车出发时车上的人数 
	cin >> a >> n >> m >> x;
	u[1] = p[2] = a;
	for(int b = 0; b < m; ++b)
	{
    
    
		u[2] = b;
		for(int i = 3; i <= n-1; ++i)
		{
    
    
			u[i] = u[i-1] + u[i-2];
			p[i] = p[i-1] + u[i-2];
		}
		if(p[n-1] == m)
		{
    
    
			cout << p[x];
			return 0;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lq1990717/article/details/128642882