13. dfs的剪枝策略练习---正方形

题目:

代码:

import java.util.Scanner;

public class Main {
	/*
	 * 思路:
	 * (1)首先计算木棍的总长度sum,
	 * 		如果sum%4==0,则说明能构成正方形,且边长s=sum/4
	 * 		否则直接输出No
	 * (2)从第一根棍开始进行dfs(1,0);
	 *   dfs(x,k) //x:当前已找到的边数;  k:当前搜索到小木棍编号
	 *     1.如果x==4,即已找到3条边,则ok=true; (ok记录当前是否能构成正方形)
	 *     2.最优性剪枝:如果ok==true,return;(确定可以构成正方形,即可退出)
	 *     3.可行性剪枝:如果当前边长>正方形边长s,return
	 *     			如果当前边长==正方形边长s->已找到一条边,继续搜索dfs(x+1,1); (确定下一条边时,从新搜索小木棍)
	 *     			如果当前边长<s, 则遍历每一条小木棍,如果当前小木棍i没有使用,则dfs(x,k+1)
测试数据
5
1 2 3 3 3
正常输出:
YES
	 * */
	static int n;//n个小木棍
	static int[] g;//小木棍长度
	static boolean[] v;//标记小木棍是否访问过
	static int s=0;//记录正方形边长
	static boolean ok=false;//记录是否能构成正方形
	static int[] len = new int[4];//记录当前边长的长度
	public static void main(String[] args){
		//1.输入相关值
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		g = new int[n];
		v = new boolean[n];
		
		int sum=0;
		for(int i=0;i<n;i++) {
			g[i] = sc.nextInt();
			sum+=g[i];
		}
		//2.计算边长
		if(sum%4==0) {
			s = sum/4;
		}else {//边长不合法
			System.out.println("NO");
			System.exit(0);
		}
		//3.深度优先遍历,寻找是否能构成正方形
		dfs(1,0);
		
		//4.输出结果
		if(ok) {
			System.out.println("YES");
		}else {
			System.out.println("NO");
		}
	}
	/*
	 * cnt:当前在确定的第cnt条边
	 * k:从编号k开始搜索小木棍
	 * */
	private static void dfs(int cnt, int k) {
		//1.当前在确定第4条边,已经确定了3条边
		if(cnt==4) {
			ok=true;
			return;
		}
		//2.已确定可构成正方形
		if(ok) {
			return;
		}
		//3.当前边的长度大于s(下标从0开始)
		if(len[cnt-1]>s) {
			return;
		}
		//4.当前边的长度等于s,继续确定下一条边
		if(len[cnt-1]==s) {
			dfs(cnt+1,1);
		}else {//5.当前边的长度 小于 s,继续添加小木棍
			for(int i=k;i<n;i++) {
				if(!v[i]) {
					v[i]=true;
					len[cnt-1]+=g[i];//将当前小木棍i累加到当前边上
					dfs(cnt,i+1);//继续遍历
					
					len[cnt-1]-=g[i];//回溯
					v[i]=false;
				}
			}
			
		}
	}
	
}
	

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值