• 种树——拼多多笔试题(暴搜+剪枝)


    题意

    链接: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("-");
    		}
    	}
    }
    

      

  • 相关阅读:
    防止vue文件中的样式出现‘污染’情况(html5 scoped特性)
    Vue.js中滚动条加载更多数据
    本地上传文件至服务器的技巧(linux文件压缩及解压文件)
    ubuntu下apache新建虚拟主机
    laravel5.4+vue+element简单搭建(gulp+laravel Elixir)
    java基础---->Java的格式化输出
    markdown 基本语法(转载)
    谷歌断点调试
    mac 远程连接 云服务器
    棋盘覆盖问题
  • 原文地址:https://www.cnblogs.com/mcq1999/p/12094247.html
Copyright © 2020-2023  润新知