木棍拼正方形 Stick To Square
一个整数组sticks
代表一堆木棍的长度,木棍不能折断,但是可以连接。每一个木棍都要使用到。判断给的木棍能否拼成一个正方形。
sticks= [1,1,2,2,2]
out:true
思路
使用DFS
,
首先,对数组做一个非递减排序。计算所有木棍长度和sum。如果sum%4!=0,说明无法拼成一个正方形。
否则进入dfs
,准备寻找可能的方案。建立一个数组arr保存每条边剩余需要木棍的长度。
总共有n个木棍,从最长的第n个木棍开始向前处理,设定如果走完所有的木棍,ind==-1时,找到了正确的方案。
循环 对4条边尝试放入第ind个木棍,如果arr[i]<ms[ind],说明木棍比这个边剩余的长度还长,不能放在arr[i],寻找下一个i。否则就会出现2个情况,
- arr[i]==ms[ind] 木棍长度刚好等于第i个边剩余的长度,arr[i]-=ms[ind],然后继续
dfs
,此时要处理的是ms[ind-1]。 - arr[i]>ms[ind] 木棍长度刚好大于第i个边剩余的长度,但是如果大于的话,说明要满足正方形方案的话,还要一个ms[?]来填。此时ms[0]是最小的木棍,如果不满足arr[i]>=ms[ind]+ms[0],说明arr[i]是无法通过ms[ind]配合其他木棍来填的。
通过上面的2个情况来缩小dfs
的分支。
public boolean makesquare(int[] sticks) {
Arrays.sort(sticks);// s to l
int sum =0;
for(int i=0;i<sticks.length;i++){
sum+= sticks[i];
}
if(sum%4!=0){
return false;
}
int[] arr = new int[4];
for(int i=0;i<arr.length;i++){
arr[i]=sum/4;
}
return dfs(sticks.length-1,arr,sticks);
}
public boolean dfs(int ind ,int[] arr,int[] ms){
if(ind==-1){
return true;
}
for(int i = 0;i<4;i++){
if(arr[i]<ms[ind]){
continue;
}
if(arr[i]==ms[ind]||arr[i]>=ms[ind]+ms[0] ){
arr[i]-=ms[ind];
if(dfs(ind-1,arr,ms)){
return true;
}
arr[i]+=ms[ind];
}
}
return false;
}
Tag
DFS