想看更多的解題報告: http://blog.csdn.net/wangjian8006/article/details/7870410
轉載請註明出處:http://blog.csdn.net/wangjian8006
題目大意:給出n條木棍的長度,將這些木棍頭尾相接,問能不能組成一個正方形,如果可以,那麼輸出yes,否則輸出no
解題思路:搜索,加一些剪枝,搜索大致這樣描述,將木棍從小到大排序,之後取木棍,如果可以組成一條邊,那麼再從開始取木棍組邊。
直到取到4條邊爲止
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXV 25
int nStickCount; //木棍個數
int nStickLength[MAXV]; //保存每個木棍的長度
int nBorderLength; //如果這些木棍可以組成正方形,這是正方形的邊長
int vis[MAXV]; //標記某條木棍是否被選中
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int dfs(int nNowBorderCount,int nExitBorder,int cur){
int i;
if(nExitBorder == 4){ //如果已經找到了4條邊,則直接返回true
return 1;
}
if(nNowBorderCount == nBorderLength){ //如果當前木棍總長度等於邊的長度
return dfs(0,nExitBorder+1,cur); //將當前木棍長度清零,找到邊數+1
}
for(i = cur;i < nStickCount;i ++){ //從cur後面繼續找
if(!vis[i-1] && nStickLength[i] == nStickLength[i - 1]){ //如果前面一條木棍沒被取中,但是當前木棍長度等於前木棍長度,那麼不做處理
continue;
}
if(!vis[i]){ //如果此木棍已經被找到,那麼不做處理
if(nNowBorderCount + nStickLength[i] < nBorderLength){ //下面做遞歸操作,假設取i這條木棍,如果可以尋找到4條邊,那麼返回1
vis[i] = 1;
if(dfs(nNowBorderCount + nStickLength[i],nExitBorder,i+1)){
return 1;
}
vis[i] = 0;
}
if(nNowBorderCount + nStickLength[i] == nBorderLength){
vis[i] = 1;
if(dfs(0,nExitBorder + 1,0)){
return 1;
}
vis[i] = 0;
}
}
}
return 0; //做以上操作都沒結果,那麼返回0,找不到
}
int main(){
int Case,i,nSum;
scanf("%d",&Case);
while(Case--){
scanf("%d",&nStickCount);
nSum = 0;
for(i = 0;i < nStickCount;i++){
scanf("%d",&nStickLength[i]);
nSum += nStickLength[i];
}
qsort(nStickLength,nStickCount,sizeof(int),cmp); //將木棍長度從小到大排序
if(nSum%4!=0){ //如果總的棍長對4取餘不爲0,那麼肯定不能組成正方形
printf("no\n");
}else{
nBorderLength = nSum/4; //得到如果可以組成正方形,那麼算出邊長
memset(vis,0,sizeof(vis)); //初始化每個木棍沒被取中
if(dfs(0,0,0)){
printf("yes\n");
}else{
printf("no\n");
}
}
}
return 0;
}