想看更多的解题报告: 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;
}