第十三届蓝桥杯大赛软件赛省赛 Java 大学 B 组
试题 G: 数组切分
时间限制: 1.0s 内存限制: 512.0MB 本题总分:20 分
题目
【问题描述】
已知一个长度为 N 的数组:A1, A2, A3, …AN 恰好是 1 ∼ N 的一个排列。
现在要求你将 A 数组切分成若干个 (最少一个,最多 N 个) 连续的子数组,
并且 每个子数组中包含的整数恰好可以组成一段连续的自然数。
例如对于 A = {1, 3, 2, 4}, 一共有 5 种切分方法:
{1}{3}{2}{4}:每个单独的数显然是 (长度为 1 的) 一段连续的自然数。
{1}{3, 2}{4}:{3, 2} 包含 2 到 3,是 一段连续的自然数,另外 {1} 和 {4} 显然 也是。
{1}{3, 2, 4}:{3, 2, 4} 包含 2 到 4,是 一段连续的自然数,另外 {1} 显然也是。
{1, 3, 2}{4}:{1, 3, 2} 包含 1 到 3,是 一段连续的自然数,另外 {4} 显然也是。
{1, 3, 2, 4}:只有一个子数组,包含 1 到 4,是 一段连续的自然数。
【输入格式】
第一行包含一个整数 N。第二行包含 N 个整数,代表 A 数组。
【输出格式】
输出一个整数表示答案。由于答案可能很大,所以输出其对 1000000007 取 模后的值
【样例输入】
4 1 3 2 4
【样例输出】
5
【评测用例规模与约定】
对于 30% 评测用例,1 ≤ N ≤ 20. 对于 100% 评测用例,1 ≤ N ≤ 10000.
代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class Main {
private static long cnt = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for(int i = 0;i < arr.length;i++) {
arr[i] = sc.nextInt();
}
fun(arr, "", 1);
System.out.println(cnt % 1000000007);
}
public static void fun(int[] arr,String str,int c) {
if(c > arr.length) {
String[] group = str.split(";");
for(String string : group) {
String[] nums = string.split(",");
ArrayList<Integer> list = new ArrayList<>();
for(String num : nums) {
if(num != "")
list.add(Integer.valueOf(num));
}
Collections.sort(list);
for(int i = 1;i < list.size();i++) {
if(list.get(i) - list.get(i - 1) != 1) {
return;
}
}
}
cnt++;
}else {
str += arr[c - 1] + ",";
fun(arr, str + ";", c + 1);
if(c != arr.length) {
fun(arr, str, c + 1);
}
}
}
}
小结
-
public class Main { private static long cnt = 0; //cnt ~ 结果 public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] arr = new int[n]; for(int i = 0;i < arr.length;i++) { arr[i] = sc.nextInt(); } fun(arr, "", 1); System.out.println(cnt % 1000000007); } /* arr ~ 源数组 str ~ 获取arr中各元素,并通过增加“,”“;”以分组 c ~ 层数,判断是否终止调用 */ public static void fun(int[] arr,String str,int c) { if(c > arr.length) { String[] group = str.split(";"); //若干个子数组group for(String string : group) { String[] nums = string.split(","); //子数组中包含的各整数nums ArrayList<Integer> list = new ArrayList<>(); for(String num : nums) { if(num != "") list.add(Integer.valueOf(num)); } Collections.sort(list); //排序,以判断是否是“连续的自然数” for(int i = 1;i < list.size();i++) { if(list.get(i) - list.get(i - 1) != 1) { return; //不符合情况,返回 } } } cnt++; //满足题意,结果加一 }else { str += arr[c - 1] + ","; //获取各整数 fun(arr, str + ";", c + 1); //在此处分组,并递归 if(c != arr.length) { //当取得最后一个整数时,所谓在此处分组,不分组是同一种情况,故略去其中一个 fun(arr, str, c + 1); //在此处不分组,并递归 } } } }
-
好傻啊我,当时以为有数学规律,列了一大堆,终是没发现
-
代码应该还可以再优雅些,暂时就这样吧,看多写多了,就会好些