练习题 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  

 

 

posted @ 2017-12-28 16:44  proscientist  阅读(193)  评论(0编辑  收藏  举报