题意
链接:https://www.nowcoder.com/questionTerminal/52f25c8a8d414f8f8fe46d4e62ef732c
来源:牛客网
小多想在美化一下自己的庄园。他的庄园毗邻一条小河,他希望在河边种一排树,共 M 棵。小多采购了 N 个品种的树,每个品种的数量是 Ai (树的总数量恰好为 M)。但是他希望任意两棵相邻的树不是同一品种的。小多请你帮忙设计一种满足要求的种树方案。
输入描述:
第一行包含一个正整数 N,表示树的品种数量。
第二行包含 N 个正整数,第 i (1 <= i <= N) 个数表示第 i 个品种的树的数量。
数据范围:
1 <= N <= 1000
1 <= M <= 2000
输出描述:
输出一行,包含 M 个正整数,分别表示第 i 棵树的品种编号 (品种编号从1到 N)。若存在多种可行方案,则输出字典序最小的方案。若不存在满足条件的方案,则输出"-"。
思路
直接搜索,看上去复杂度是阶乘级,但剪枝后就能过了,玄学。剪枝点是当出现一种树的数量大于剩余树的1/2时,就不满足条件了。
代码
import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main { static final int N = 1005; static int[] a = new int[N]; static int m=0,n,flag=0; static List<Integer> ans=new ArrayList<Integer>(); static void dfs(int cnt) { for(int i=1;i<=n;i++) { if(a[i]>(m-cnt+1)/2) return ; } if(cnt==m) { flag=1; return ; } for(int i=1;i<=n;i++) { if(cnt==0||(a[i]>0&&ans.get(ans.size()-1)!=i)) { a[i]--; ans.add(i); dfs(cnt+1); if(flag==1) return ; ans.remove(ans.size()-1); a[i]++; } } } public static void main(String[] args) { Scanner in = new Scanner(System.in); n = in.nextInt(); for (int i = 1; i <= n; i++) { a[i] = in.nextInt(); m += a[i]; } dfs(0); if(flag==1) { for(int i:ans) { System.out.print(i+" "); } System.out.println(); }else { System.out.println("-"); } } }