蓝桥杯20151 跳石头

问题描述

小明正在和朋友们玩跳石头的小游戏,一共有 n 块石头按 1 到 n 顺序排成一排,第 i 块石头上写有正整数权值 ci​ 。

如果某一时刻小明在第 j 块石头,那么他可以选择跳向第 j+cj​ 块石头 (前提 j+cj≤n )或者跳向第 2j 块石头(前提 2j≤n),没有可跳跃的目标时游戏结束。

假如小明选择从第 x 块石头开始跳跃,如果某块石头有可能被小明经过 ("经过"指存在某一时刻小明在这个石头处),则将这块石头的权值纳入得分集合 Sx​ ,那么小明从第 x 块石头开始跳跃的得分为 ∣Sx∣。

比如如果小明从第 x 块石头出发,所有可能经过的石头上的权值分别为 5,3,5,2,3 ,那么 Sx=5,3,2 得分为 ∣Sx∣=3 。小明可以任选一块石头开始跳跃,请求出小明最多能获得的分数。

输入格式

输入共 2 行。

第一行为一个正整数 n。

第二行为 n 个由空格分开的正整数 c1,c2,…,cn​。

输出格式

输出共 1 行,一个整数表示答案。

样例输入

5
4 3 5 2 1

样例输出

4

样例说明

从第一块石头出发得分最多,路径有以下几种:

  1. 1 号 →5 号:选择从 1 号跳到 1+c1=5 号。
  2. 1 号 →2 号 →5 号:第一次选择从 1 号跳到 2×1=2 号,第二次选择从 2 号跳到 2+c2=5​ 号。
  3. 1 号 →2 号 →4 号:第一次选择从 1 号跳到 2×1=2 号,第二次选择从 2 号跳到 2×2=4 号

所以所有可能经过的石头的权值的集合为 S1​={c1​,c2​,c4​,c5​}={4,3,2,1} ,得分为 ∣S1∣=4。

评测用例规模与约定

对于 20% 的评测用例,保证 n≤20 。

对于 100% 的评测用例,保证 n≤40000,ci≤n 。

 

dfs 遍历每一个石头作为起点

用 set 记录经过的石头的权值

set 最多的元素数量即为答案

#include
#include
#include
using namespace std;

int n;
const int N = 4e4+10;
int a[N];
set s;
int ans;  //得分:所有可能经过的石头上的不同权值的数量

//x:当前石头的编号 
void dfs(int x)
{
	if(x>n)
	{
		int cnt = s.size();
		ans = max(cnt, ans);
		return;
	}
	
	s.insert(a[x]);  //记录经过的所有石头的权值
	
	//“跳向第 2j 块石头” 
	dfs(2 * x);
	//“跳向第 j+cj 块石头” 
	dfs(x + a[x]);
}

int main()
{
	cin>>n;
	for(int i=1; i<=n; ++i) cin>>a[i];
	
	//遍历每一块石头,选择第 i 个石头作为起点 
	for(int i=1; i<=n; ++i)
	{
		dfs(i);  
		s.clear();
	}
	
	cout<

你可能感兴趣的:(dfs)