Transcript
Page 1: 习题选 讲(分治法)

习题选讲(分治法)

Page 2: 习题选 讲(分治法)

2

递归与分治 Rate of Return Binary Tree sicily 1935. 二叉树重建 电路稳定性 Monthly Expense Pie sicily 1028. Hanoi Tower Sequence 1211 商人的宣传 1071 Floors

Page 3: 习题选 讲(分治法)

3 2011-10-20

1017 Rate of Return

解题思路:当利润率在 [0,1]之间,假设投资额和时间不变,则利润率越高,最后的本金和利润总和越大。

因此对利润率进行二分查找,检查在假设的利润率下,比较最后的本金和利润总和与实际值,调整二分上下界,直到达到某个精度。

Page 4: 习题选 讲(分治法)

4 2011-10-20

1017 Rate of Return double find(double left,double right,int m,double x) { double center,s=0; center=(left+right)/2; if (right-left<=0.000000005) return center; for (int i=1;i<=m;i++) s+=a[i]*pow(1.0+center,m+1-i); if (s<x) return find(center,right,m,x); else return find(left,center,m,x); }

Page 5: 习题选 讲(分治法)

5

Binary Tree Given a binary tree, every node of which

contains one upper case character (‘A’ to ‘Z’); you just need to print all characters of this tree in pre-order.

Input: 4 C 1 0表示标志符为 4的点,点值为C,其左儿子为标识符为 1的点,没有右孩子。3 4 C 1 3 1 A 0 0 3 B 0 0

Output: CAB2011-12-21

Page 6: 习题选 讲(分治法)

6

二叉树重建题目大意:输入一棵二叉树的先序遍历序列和中序遍历序列,输出它的广度优先遍历序列。

例如,先序 ABCDEF,中序 CBAEDF

Page 7: 习题选 讲(分治法)

7

二叉树重建解题思路前序遍历,根节点最先被输出,所以 A是根结点。中序遍历,左子树的全部结点输出后,接着输出根结点,最后输出右子树的全部结点。

例如,先序 ABCDEF,中序 CBAEDFA

BCDE F

Page 8: 习题选 讲(分治法)

8

二叉树重建左子树:前序 BC,中序 CB右子树:前序 DEF,中序 EDF

A

BCDE F

A

B

C

DE F

A

B

C

D

E F

Page 9: 习题选 讲(分治法)

9

二叉树重建void build(int n, int dep, char* s1, char* s2){ if (n <= 0) return; int p = strchr(s2, s1[0]) - s2; lv[dep][ln[dep]++] = s1[0]; build(p, dep+1, s1+1, s2); build(n-p-1, dep+1, s1+p+1, s2+p+1);}

调用: build(strlen(s1), 0, s1, s2);

Page 10: 习题选 讲(分治法)

10

电路稳定性题目大意:给出一个电路,以及各元件断路的概率。求整个电路断路的概率。

Page 11: 习题选 讲(分治法)

11

电路稳定性 解题思路: n个元件,若它们的断路概率为 p1,p2,...,pn,则串联断路概率为 1-(1-p1)(1-p2)...(1-pn),并联断路概率为 p1p2...pn。

问题的关键点是把字符串表示的电路转化为实际电路。

http://222.200.182.58/viewsource.php?sid=87438

Page 12: 习题选 讲(分治法)

12

Monthly Expense

题目大意:农夫知道未来 N天每天的花费,他现在需要把这 N天分成连续的M段,使得花费最大的段花费最小。求这个花费。

1 <= N <= 100,000, 1 <= M <= N

Page 13: 习题选 讲(分治法)

13

Monthly Expense

解题思路:二分最高花费,再使用贪心的方法求出在这个花费下是否能把 N天分成M段且每段都不超过这个花费,从而调整二分的上下界。

Page 14: 习题选 讲(分治法)

14

Monthly Expense while(min<=max){ mid=(min+max)/2; int t=0;int num=0; for(i=0;i<n;i++){ if(num+N[i]<=mid)num+=N[i]; else {t++; if(t>m)break; num=N[i];} } if(num)t++; if(t<=m){ ans=mid; max=mid-1; } else min=mid+1; }

Page 15: 习题选 讲(分治法)

15

Pie

题目大意:一共有 N个派和 F+1个人,每个人分到一份派,要求每个人分到的派的大小相等,问最大的面积是多少。

1 ≤ N, F ≤ 10 000

Page 16: 习题选 讲(分治法)

16

Pie

解题思路:二分派的大小,再使用贪心的方法求出在这个大小下,是否足够分给所有人,从而调整二分的上下界。

Page 17: 习题选 讲(分治法)

17

Pie

while(max-min>1e-5){ mid=(min+max)/2.0; int sum=0; for(i=0;i<n;i++) sum+=(int)(N[i]/mid); if(sum<f) max=mid; else min=mid; }

Page 18: 习题选 讲(分治法)

18 2011-10-20

1028 Hanoi Tower Sequence

题目大意:定义汉诺塔,共有三个柱子和很多的大小两两不同的盘子放在一个柱子上,要求把它们移到另一个柱子上,每次只能移动一个放在柱子最顶端的盘子,并且每次移动后需保证较小的盘子在较大的盘子上面。给出步数 p,求第 p步移动的盘子的大小。

p<=10^100

Page 19: 习题选 讲(分治法)

19 2011-10-20

1028 Hanoi Tower Sequence

解题思路: n个盘子的汉诺塔问题递归求解:把前 n-1个盘子移到第二根柱子上,把第 n个盘子移到第三根柱子上,把前 n-1个盘子移到第三根柱子上。

从一根柱子到另一根柱子,移动 1个盘子需要f(1)=1步,移动 k(k>1)个盘子需要 f(k)=f(k-1)+1+f(k-1)步。

即得到 f(k)=2^k-1。因此第 2^k步移动的是 k+1个盘子。在移动第 k+1个盘子后,左右对移地移动 k个盘子。

Page 20: 习题选 讲(分治法)

20 2011-10-20

1028 Hanoi Tower Sequence

把 p化成二进制数,假设现在 p里有超过1个位为 1,设最高位为 k,则在 2^k步前和 2^k步后对称,因此第 p步移的盘子与第 p-2^k步移的盘子一样。

直到 p里只有 1个位为 1,设此时p=2^m,则此步移动的是第m+1个盘子。

因此题目转化成二进制数 p,从低位起连续 0的位数,加 1,为答案。

Page 21: 习题选 讲(分治法)

21 2011-10-20

1028 Hanoi Tower Sequence

int cal(int a[],int n) { int cnt=1; while (a[n-1]%2==0) { cnt++; for (int i=0,temp=0;i<n;i++) { temp=temp*10+a[i]; a[i]=temp/2; temp%=2; } } return cnt; }

Page 22: 习题选 讲(分治法)

22 2011-10-20

1211 商人的宣传题目大意:有 n个州,m条单向边,规定天数为 L。共有 q个询问,每个询问为从州 A到州 B刚好为 L步的方案数。

Page 23: 习题选 讲(分治法)

23 2011-10-20

1211 商人的宣传解题思路:第 0天,每个州到自己的方案数为 1。第 n+1天,每个州 A到另一个州 B的方案数为,对所有州 C,第 n天从 A到 C的方案数与一天内从 C到 B的方案数的积,再对所有州求和。(即第 n天通过州 C作中转的方案)

Page 24: 习题选 讲(分治法)

24 2011-10-20

1211 商人的宣传 int cal(int A,int B) { int i,j,k; memset(ans,0,sizeof(ans)); ans[0][A][A]=1; for (k=1;k<=L;k++) { for (i=1;i<=n;i++) for (j=1;j<=n;j++) ans[k][A][i]+=ans[k-1][A][j]*edge[j][i]; return ans[L][A][B]; }

Page 25: 习题选 讲(分治法)

25 2011-10-20

1071 Floors

题目大意:一块长方形地板是由很多长方形瓷砖组成的,每次可以从中选一块,沿着瓷砖的边缘按直线切成两块,直到没有任何块可以继续此操作。求出此时最大的块的面积。

Page 26: 习题选 讲(分治法)

26 2011-10-20

1071 Floors

解题思路:对于每一块,尝试平行于长方形的两边分别切割。对于分出来的小块,递归进行重复操作。

判断是否可切割:按垂直于切割方向对瓷砖进行排序,切割线所切出来的块的面积与所在一侧的瓷砖总面积之和相等,则可切割。

Page 27: 习题选 讲(分治法)

27 2011-10-20

1071 Floors

void cal(int x1,int y1,int x2,int y2,int l,int r) { int s=(x2-x1)*(y2-y1); if (s<=ans) return; if (cutx(x1,y1,x2,y2,l,r)) return; if (cuty(x1,y1,x2,y2,l,r)) return; if (s>ans) ans=s; }

Page 28: 习题选 讲(分治法)

28 2011-10-20

1071 Floors bool cmpx(const rect &a,const rect &b) { return

a.xl<b.xl; } bool cutx(int x1,int y1,int x2,int y2,int l,int r) { sort(a+l,a+r+1,cmpx); int x=x1,s=0; for (i=l;i<r;i++) { s+=a[i].s; if (a[i].xh>x) x=a[i].xh; if (s==(x-x1)*(y2-y1)) { cal(x1,y1,x,y2,l,i); cal(x,y1,x2,y2,i+1,r); return true; } } return false; }

Page 29: 习题选 讲(分治法)

29

谢谢!


Recommended