原题链接:蓝桥杯2018年第九届真题-小朋友崇拜圈
如果题目没看懂,没看懂就对了,因为题目并不完整,下面是完整题目。

假设输入的n个数字存储在 nums[]中,那么nums[i]表示第i个小朋友崇拜的是 nums[i]。

这题是找出最大的那个圈中小朋友的个数,从这个图可以看出共有三个圈,其中从2开始到2结束的圈最大。
既然第i个小朋友的下一个小朋友是nums[i] ,
那么就根据i得到nums[i],根据nums[i]得到nums[i]崇拜的小朋友,
next= nums[i] 下一个小朋友
这里使用dp[]存储小朋友个数,dp[next]=dp[i]+1;
直到遇到一个已经判断过的小朋友,也就是dp[i]!=0时退出循环。
两种写法,思路相同
循环法的耗时更短,因为使用set记录已经走过的点,去除很多重复的运算。
循环法,搜索法
1,循环法,
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class Main {
/**
* @param args
*/
public static Set<Integer> vis=new HashSet<Integer>();//记录已经走过的点
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n+1];
for (int i = 1; i <=n; i++) {
nums[i] = sc.nextInt();
}
int max = 0;
for (int i = 1; i <=n; i++) {
int dp[]=new int[n+1];//当前 到达第i个小朋友的步数
if (vis.contains(i)) {//不用找了
continue;
}
max=Math.max(check(nums, dp, i), max);
}
System.out.println(max);
}
public static int check(int nums[],int dp[],int step) {
vis.add(step);//走过step点
dp[step]=1;
while (dp[nums[step]]==0) {//没走过
int next=nums[step];
dp[next]=dp[step]+1;
step=next;
vis.add(step);//走过step点
}
return dp[step]-dp[nums[step]]+1;
}
}搜索
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n+1];
for (int i = 1; i <=n; i++) {
nums[i] = sc.nextInt();
}
int max = 0;
for (int i = 1; i <=n; i++) {
int dp[]=new int[n+1];//当前 到达第i个小朋友的步数
dp[i]=1;
max=Math.max(dfs(nums, dp, i), max);
}
System.out.println(max);
}
public static int dfs(int nums[],int dp[],int step) {
int next=nums[step];//下一个点
if (next==step) {
return 0;
}
if (dp[next]!=0) {
return dp[step]-dp[next]+1;//得到循环的大小
}else {
dp[next]=dp[step]+1;
int _ans= dfs(nums, dp, next);
return _ans;
}
}
}搜索2,
将已经得到的答案存储起来,下一次直接可以直接使用。优化速度。
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class Main {
/**
* @param args
*/
public static int tAns[];//将已知的答案记录下来
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n+1];
tAns=new int[n+1];
for (int i = 1; i <=n; i++) {
nums[i] = sc.nextInt();
}
int max = 0;
for (int i = 1; i <=n; i++) {
int dp[]=new int[n+1];//当前 到达第i个小朋友的步数
dp[i]=1;
if (tAns[i]!=0) {
max=Math.max(tAns[i], max);
}else {
max=Math.max(dfs(nums, dp, i), max);
}
}
System.out.println(max);
}
public static int dfs(int nums[],int dp[],int step) {
int next=nums[step];//下一个点
if (next==step) {
return 0;
}
if (tAns[step]!=0) {//返回已知的答案
return tAns[step];
}
if (dp[next]!=0) {
return tAns[step]=dp[step]-dp[next]+1;//得到循环的大小
}else {
dp[next]=dp[step]+1;
int _ans= dfs(nums, dp, next);
return _ans;
}
}
}0.0分
2 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复