POJ 2362 Square
阿新 • • 發佈:2019-02-08
題目大意:給n根長度不一的木棍,問是否能構成一個正方形
解題思路:由於題目限定4<=n<=20,可以直接用DFS,但是必須剪枝。首先可以很容易得到以下兩個剪枝條件:
a . 木棍總長度sum必須可以被4整除
b . 最長的木棍的長度不得長於正方形邊長
根據這兩個條件之後,如果可以拼湊出正方形的3條邊,由於sum一定,那麼就一定可以組成一個正方形,否則輸出”no”.所以
c . 深搜能得到正方形的三條邊即可。**
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
int n;//木棍個數
bool visit[21];//是否被訪問
int stick[21];//木棍長度
int side;//正方形邊長
bool cmp(int a,int b)
{
return a>b;
}
bool dfs(int num,int len,int root)
{//num為成功湊成的邊數
//len為當前正在拼湊的邊的長度
//root為起始訪問的木棍陣列的下標
if(num==3)
return true;
for(int i=root;i<n;i++)
{
if (visit[i])
continue;
visit[i]=true;
if(len+stick[i]<side)//若小於side
{
if(dfs(num,len+stick[i],i+1))//加上stick[i]產生新len,
return true; //i+1可以避免沒有意義的迴圈
//else visit[i]=false;
//若加上stick[i]後使得無法成功拼成正方形,則放棄當前邊
}
else if(len+stick[i]==side)//若相等,則開始拼湊下一條邊
{
if(dfs(num+1,0,0))
return true;
//else visit[i]=false;
//同上
}
visit[i]=false;//若大於side則暫時放棄當前邊
}
return false;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n;int sum=0;
for(int i=0;i<n;i++)
{
cin>>stick[i];
sum+=stick[i];
}
sort(stick,stick+n,cmp);//先將木棍長度按照降序排列
side=sum/4;
memset(visit,false,sizeof(visit));
if(sum%4!=0||stick[0]>side)//剪枝1:總長度不能被4整除
{ //剪枝2:最長木棍長於正方形邊長
cout<<"no"<<endl;
continue;
}
if(dfs(0,0,0))
cout<<"yes"<<endl;
else
cout<<"no"<<endl;
}
return 0;
}