练习题 POJ1011/The Biggest Rectangle
题目:DFS练习题目
1 /*POJ 1011 2 题目:给最多64根棍,每根最长50,拼成等长的几个片段,不能有剩余,问最短的片段长度。 3 使用DFS+强剪枝 4 */ 5 #include <stdio.h> 6 #define SIZE 65 7 int num[SIZE], n, max, sum, isFind, key; 8 void dfs(int cnt, int len, int cur){//已用的条数,凑成key还需的长度,当前位置 9 if (isFind > 0)return; 10 if (cnt == n - 1 && cur == len){ 11 isFind = 1; 12 return; 13 } 14 --num[cur];//当前点合法,加入解空间 15 int nextcur; 16 if (cur == len){//填上这一条就能凑成一个key长度的片段 17 for (nextcur = max; nextcur > 0; --nextcur) 18 if (num[nextcur] > 0)break; 19 dfs(cnt + 1, key, nextcur); 20 }else{ 21 for (nextcur = cur; nextcur > 0; --nextcur){ 22 if (nextcur > len - cur || num[nextcur] == 0)continue; 23 dfs(cnt + 1, len - cur, nextcur); 24 } 25 } 26 ++num[cur]; 27 } 28 int main(){ 29 int tdata; 30 #ifndef ONLINE_JUDGE 31 freopen("sample_input.txt", "r", stdin); 32 #endif 33 while (~scanf("%d", &n) && n){ 34 for (int i = 0; i < SIZE; ++i)num[i] = 0; 35 sum = max = isFind = 0; 36 for (int i = 0; i < n; ++i){ 37 scanf("%d", &tdata); 38 ++num[tdata]; 39 sum += tdata; 40 if (tdata>max)max = tdata; 41 } 42 isFind = -1; 43 for (key = max; key <= sum / 2; ++key){ 44 if (sum%key > 0)continue; 45 dfs(0, key, max); 46 if (isFind > 0){ 47 printf("%d\n", key); 48 break; 49 } 50 } 51 if (isFind < 0)printf("%d\n", sum);; 52 } 53 return 0; 54 }
附上一道相似的题目,给定一些木棒,求可拼接出的最大矩形面积。
Execution time : 10 sec(C/C++) / 20 sec(JAVA) for 95 cases combined
Memory : Maximum 256MB available for heap and stack combined (note: Maximum 1 MB can be used for stack)
题目描述:
Suppose there are N sticks.
Write a program that figures out out the area of the biggest rectangle among rectangles that could be made with those sticks.
To make a rectangle,you can can connect sticks together but you cannot splict an intact stick.
For example, you can make a stick of length 6 by joining a stick of length 2 with a stick of length 4.
[Input]
The first line contains a single integer Tㅡthe number of total test cases.
The first line of each test case contains one positive integer, N( 4 ≤ N ≤ 16).
The second line contains N space-separated positive integers which represent the lengths of N sticks.
The length of a stick is a positive integer greater than or equal to 1 and less than and equal to 10.
[Output]
Each line begins with ‘#T’(Test case number) followed by a space and then print the area of the biggest possible rectangle for each test case.
If it is not possible to make a rectangle with the given sticks, print -1.
input 下载链接:https://files.cnblogs.com/files/proscientist/biggest_rect_input.zip
题解:DFS题目,配合剪枝
1 /*The Biggest Rectangle 2 题意:给定最多16根棍,选取其中一些拼成矩形,问矩形最大面积 3 */ 4 #include <stdio.h> 5 int tc, n, s[17], la, lb, sum, ans, k; 6 bool visit[17]; 7 void dfs(int loc, int cnt, int cur, int dep){ 8 if (dep == 4){ 9 ans = la*lb; 10 return; 11 } 12 if (cnt == 2){ 13 lb = k; 14 while (lb > 0){ 15 if (la*lb < ans)return; 16 dfs(n, 0, lb, dep); 17 --lb; 18 } 19 return; 20 } 21 int last = -1; 22 for (int i = loc - 1; i >= 0; i--){ 23 if (visit[i] || s[i] == last)continue; 24 if (cur == s[i]){ 25 visit[i] = 1; 26 if (dep<2)dfs(n, cnt + 1, la, dep + 1); 27 else dfs(n, cnt + 1, lb, dep + 1); 28 visit[i] = 0; 29 last = s[i]; 30 } 31 if (cur > s[i]){ 32 visit[i] = 1; 33 dfs(i, cnt, cur - s[i], dep); 34 visit[i] = 0; 35 last = s[i]; 36 } 37 } 38 } 39 int main(){ 40 scanf("%d", &tc); 41 for (int t = 1; t <= tc; ++t){ 42 ans = -1, sum = 0; 43 scanf("%d", &n); 44 //读入数据以及排序,sum 45 for (la = sum / 2 - 1; la > 0; --la){//长边 46 k = (sum - 2 * la) / 2; 47 if (k > la)k = la; 48 if (k*la <= ans)continue; 49 dfs(n, 0, la, 0); 50 } 51 printf("#%d %d\n", t, ans); 52 } 53 return 0; 54 } 55