原题链接: http://acm.hdu.edu.cn/showproblem.php?pid=1518
一:原题内容
3 4 1 1 1 1 5 10 20 30 40 50 8 1 7 2 6 4 4 3 5
yes no yes
二:理解分析
给定一堆棍子,问是否能构造出一个正方形,当然所有棍子都要使用。首先判断所有棍子长度是否能整除4,不能的话,肯定不是正方形,其次棍子中最长的那根,是否大于正方形的边长呢?大于的话,当然也是不能组成正方形的。
三:AC代码
#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 #include<iostream> #include<algorithm> #include<string.h> using namespace std; bool visit[21]; int square[21]; int N; int M; int sum; //周长长度 int len; //边长长度 bool flag; //标记是否已找到正方形 void DFS(int, int, int); int main() { scanf("%d", &N); while (N--) { scanf("%d", &M); memset(visit, 0, sizeof(visit)); sum = 0; flag = false; for (int i = 0; i < M; i++) { scanf("%d", &square[i]); sum += square[i]; } sort(square, square + M);//排序 len = sum / 4;//求出边长 if (sum % 4 == 0 && square[M - 1] <= len)//周长能整除4且所给长度的最大值小于等于边长才有可能构造出正方形 DFS(0, M - 1, 0); if (flag) printf("yes\n"); else printf("no\n"); } return 0; } void DFS(int sideLen, int k, int number)//sideLen代表当前正在构造的边长长度;number标记当前已经有多少条边构造出来了,当有三条边已构造出来,那么根据正方形的性质,说明此时这些棍子是可以组成正方形的 { if (sideLen == len)//已成功构造出一条边长 { number++;//这个地方起初是设置为全局变量(也就是DFS函数的第三参数起初是没有的),但是交上去WA了,最后才发现是这里错了。 sideLen = 0; k = M - 1; } if (number == 3)//正方形已构造出 { flag = 1; return; } if (flag) return; for (int i = k; i >= 0; i--) { if (!visit[i] && square[i] + sideLen <= len)//如果这根棍子没有使用过并且当前正在构造的边长加上这个棍子的总长度也是不大于边长的,那就可以了 { visit[i] = 1; DFS(sideLen + square[i], i - 1, number); if (flag) return; visit[i] = 0; while (square[i - 1] == square[i]) i--; if (len - sideLen == square[i]) return; if (sideLen == 0) return; } } }
参考链接: http://www.acmerblog.com/hdu-1518-Square-2075.html