[b]题意分析:[/b]
给出4个长方形的高和长,以及给出6种基本布局,求合成无重叠的最小面积时的长和宽。
[b]解题思路:[/b]
这一题比较容易成为被卡住的第一题。
【首先】使用贪心的念头不要有,必须老老实实地将所有情况列出,那到底有多少情况呢?
1.六种基本布局中,第四种与第五种实则为一种,布局为5种。
2.在每种布局中,由于长方形摆放的位置不同,有4的阶乘种。
3.不同布局,不同摆放位置的每个长方形都有横竖两种摆法,有2的4次方种。
综上:共有 5 × 4! × 2^4 = 1920种。
【其次】要回忆一下[b]回溯法[/b]。
在S1×S2×S3×…×Sn中,求解向量X=(x1,x2,x3…xn)。
算法描述:
子集树和排列树为常见的两种解空间树。
[b]子集树:[/b]遍历子集树需要O(n^2)的时间
[b]排列树:[/b]遍历排列树需要O(n!)的时间
[b]回溯法backtracking经常会和术语深度优先遍历DFS(Depth First Search)混用,它们有什么差别呢?
[/b]非要深究的话,深度优先搜索是一种遍历真实存在的图或树的方法。而回溯法则是遍历整个问题空间寻找一个解决方案。回溯法是一个更通用的算法,问题本身并不一定与树相关。
【最后】在于每种布局的情况讨论,(这里的h与w,h不一定大于w,反之亦然)
[img]http://dl.iteye.com/upload/attachment/517267/e06aa6b2-2329-3790-82d5-7878a85225b0.bmp[/img]
第六种情况的width则要进一步分情况讨论:
[img]http://dl.iteye.com/upload/attachment/517264/d5f75005-ab3e-3353-b5be-db763d577a78.bmp[/img]
[b]代码实现:[/b]
[url]https://github.com/leonlu/USACOJavaSolution/blob/master/USACOSection1/src/packrec.java[/url]
给出4个长方形的高和长,以及给出6种基本布局,求合成无重叠的最小面积时的长和宽。
[b]解题思路:[/b]
这一题比较容易成为被卡住的第一题。
【首先】使用贪心的念头不要有,必须老老实实地将所有情况列出,那到底有多少情况呢?
1.六种基本布局中,第四种与第五种实则为一种,布局为5种。
2.在每种布局中,由于长方形摆放的位置不同,有4的阶乘种。
3.不同布局,不同摆放位置的每个长方形都有横竖两种摆法,有2的4次方种。
综上:共有 5 × 4! × 2^4 = 1920种。
【其次】要回忆一下[b]回溯法[/b]。
在S1×S2×S3×…×Sn中,求解向量X=(x1,x2,x3…xn)。
算法描述:
1.令解向量X={}
2.flag=false;
3.advance(1)
4.if(flag) 输出解X
5.else 输出无解
advance(int t):
对每一个x属于St循环执行:
X[t] = x; //将xt加入X
if(X是最终解)flag=true; return;
else if(X是部分解)advance(t+1); //搜索下一层
else(X不是最终解也不是部分解)continue;
子集树和排列树为常见的两种解空间树。
[b]子集树:[/b]遍历子集树需要O(n^2)的时间
void backtrack (int t){
if (t>n) output(X); // X是最终解
else{
X[t]=true;
if (legal(t)) backtrack (t+1); // X是部分解
X[t]= false;
if (legal(t)) backtrack (t+1); // X是部分解
}
}
[b]排列树:[/b]遍历排列树需要O(n!)的时间
void backtrack (int t)
{
if (t>n) output(X); // X是最终解
else
for (int i=t;i<=n;i++) {
swap(x[t], x[i]);
if (legal(t)) backtrack(t+1); // X是部分解
swap(x[t], x[i]);
}
}
[b]回溯法backtracking经常会和术语深度优先遍历DFS(Depth First Search)混用,它们有什么差别呢?
[/b]非要深究的话,深度优先搜索是一种遍历真实存在的图或树的方法。而回溯法则是遍历整个问题空间寻找一个解决方案。回溯法是一个更通用的算法,问题本身并不一定与树相关。
【最后】在于每种布局的情况讨论,(这里的h与w,h不一定大于w,反之亦然)
[img]http://dl.iteye.com/upload/attachment/517267/e06aa6b2-2329-3790-82d5-7878a85225b0.bmp[/img]
//1:
int width = w1 + w2 + w3 + w4;
int height = max(max(h1, h2),max(h3, h4));
//2:
height = w1 + max(max(h2, h3),h4);
width = max(h1, w2 + w3 + w4);
a[1] = new Rectangle(width, height);
//3:
height = max(h1, w2 + max(h3, h4));
width = w1 + max(h2, w3 + w4);
a[2] = new Rectangle(width, height);
//4,5:
width = max(w2,w4) + w1 + w3;
height= max(max(h1, h3),h2 + h4);
//6:
height = max(h1+h3, h2+h4);
第六种情况的width则要进一步分情况讨论:
[img]http://dl.iteye.com/upload/attachment/517264/d5f75005-ab3e-3353-b5be-db763d577a78.bmp[/img]
if(h3 >= h2 + h4)
width = max(w1, max(w3+w2,w3+w4));
else if (h3 > h4 && h3 < h2+h4)
width = max(max(w1+w2, w2+w3),w3+w4);
else if( h3 < h4 && h4 < h1+h3)
width = max(max(w1+w2, w1+w4), w3+w4);
else if (h4 >=h1+h3)
width = max(max(w1+w4, w3+w4), w2);
else // h4 == h3
width = max(w1+w2, w3+w4);
[b]代码实现:[/b]
[url]https://github.com/leonlu/USACOJavaSolution/blob/master/USACOSection1/src/packrec.java[/url]