1 / 29

# ??? ?????? - PowerPoint PPT Presentation

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about '??? ??????' - maisie

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

### 习题选讲（分治法）

• Rate of Return

• Binary Tree

• sicily1935. 二叉树重建

• 电路稳定性

• Monthly Expense

• Pie

• sicily 1028. Hanoi Tower Sequence

• 1211 商人的宣传

• 1071 Floors

• 解题思路：

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

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

• 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);

• }

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: CAB

• 题目大意：

• 输入一棵二叉树的先序遍历序列和中序遍历序列，输出它的广度优先遍历序列。

• 例如，先序ABCDEF，中序CBAEDF

D

E

F

• 解题思路

• 前序遍历，根节点最先被输出，所以A是根结点。中序遍历，左子树的全部结点输出后，接着输出根结点，最后输出右子树的全部结点。

• 例如，先序ABCDEF，中序CBAEDF

A

B

C

D

E

F

E

C

F

E

F

B

C

D

D

• 左子树：前序BC，中序CB

• 右子树：前序DEF，中序EDF

A

A

A

B

void build(int n, intdep, 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);

}

• 题目大意：

• 给出一个电路，以及各元件断路的概率。求整个电路断路的概率。

• 解题思路：

• n个元件，若它们的断路概率为p1,p2,...,pn，则串联断路概率为1-(1-p1)(1-p2)...(1-pn)，并联断路概率为p1p2...pn。

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

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

• 题目大意：

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

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

• 解题思路：

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

• 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;

• }

• 题目大意：

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

• 1 ≤ N, F ≤ 10 000

• 解题思路：

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

• 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;

• }

• 题目大意：

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

• p<=10^100

• 解题思路：

• 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个盘子。

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

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

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

• 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;

• }

1211 商人的宣传

• 题目大意：

• 有n个州，m条单向边，规定天数为L。

• 共有q个询问，每个询问为从州A到州B刚好为L步的方案数。

1211 商人的宣传

• 解题思路：

• 第0天，每个州到自己的方案数为1。

• 第n+1天，每个州A到另一个州B的方案数为，对所有州C，第n天从A到C的方案数与一天内从C到B的方案数的积，再对所有州求和。（即第n天通过州C作中转的方案）

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];

• }

• 题目大意：

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

• 解题思路：

• 对于每一块，尝试平行于长方形的两边分别切割。对于分出来的小块，递归进行重复操作。

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

• 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;

• }

• 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;

• }