题目:
代码:
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;
}
}
}
}
}