演算法入門經典第八章學習筆記(中)

2021-06-20 11:45:10 字數 3238 閱讀 3625

有乙個2^k×2^k個方格棋盤,恰有乙個方格是灰色的,其他為白色,你的任務是用包含3個方格的l型骨牌覆蓋所有白色方格。灰色方格不能被子覆蓋,且任意乙個白色方格不能同時被兩個或更多骨牌覆蓋。如圖8-3所示為l型骨牌(三格板)的4種旋轉方式。

方法也是分治法,總牌數(4^k-1)/3 ,劃分成下面(a)這樣,第一塊和原問題一樣,但是其他三塊不行。所以這樣處理選擇乙個三格板放在(b)位置上,如圖,就可以據需處理了。

//tr表示棋盤左上角方格的行號,tc表示棋盤左上角方格的列號, 

//dr表示特殊方格所在的行號,dc表示特殊方格所在的列號,size表示方形棋盤邊長。 

//title表示l型骨牌的編號,其初始值為0

void chessboard(int tr, int tc, int dr, int dc, int size)

//覆蓋右上角棋盤

if (dr < tr+s && dc >= tc+s)

chessboard(tr, tc+s, dr, dc, s);

else

//覆蓋左下角子棋盤

if(dr>=tr+s && dc=tr+s && dc>=tc+s)

chessboard(tr+s, tc+s, dr, dc, s);

else }

void displayboard(int size) }

int main()

8.3.2  

迴圈日程表問題

設有n=2k 個運動員要進行網球迴圈賽。需要設計比賽日程表。每個選手必須與其他n-1個選手個比賽一次;每個選手一天只能賽一次;迴圈賽一共進行n-1天。按此要求設計一張比賽日程表,它有n行和n-1列,第i行第j列為第i個選手在第j天遇到的選手。

方法:遞迴。紅框是k = 1時的。

#include #include #include #include #include #include #include #include #include using namespace std;

int table [100][100];

void creattable(int r1, int c1, int r2, int c2, int size)

}int main()

return 0;

}

一次向銀行借a元錢,分b月還清。如果需要每個月還c元,月利率是多少?(按複利計算)?例如借2000元,分4個月每月510元,則月利率為0.797%。答案應不超過100%。 

方法:因為方程為:  f(x)=(((2000(1+x)-c)(1+x)-c)(1+x)-c)(1+x)-c=0很難求解x,但是注意到f(x)在x∈[0,100]內關於是單調遞增的,因此f(x)和0的關係與x和方程的解x0的大小關係等價。可以採用二分法來解決此問題。也就是去猜結果,當然首先的式子和思路要有。

#include #include #include #include #include #include #include #include #include using namespace std;

int main()

cout << setprecision(3) << fixed << x << "%" << endl;

}

注意到f(x)在x∈[0,100]內關於是單調遞增的,因此f(x)和0的關係與x和方程的解x0的大小關係等價。可以採用二分法來解決此問題。

把乙個包含n個正整數的序列劃分成m個連續的子串行(每個正整數恰好屬於乙個序列)。設i個序列的各數之和為s(i),你的任務是讓所有s(i)的最大值盡量小。例如序列1 2 3 2 5 4劃分成3個序列的最優方案為1 2 3|2 5|4,其中s(1)、s(2)、s(3)分別為6、7、 4,最大值為7;如果劃分成1 2|3 2|5 4,最大值為9,不如剛才好。n≤10^6 。所有數之和 不超過10^9 。

方法:對於這個問題:能否把輸入序列劃分成m個連續的子串行,使得所有s(i)均不超過x?此問題的答案用p(x)表示,則讓p(x)為真的最小x就是原題的答案。對p(x)計算,每次盡量往右劃分即可。

先求出序列的總和和最小值,x必定在這之間,二分判斷每個x即可。注意判定函式,從左往右,如果和大於mid,就表示前邊的是劃分出來的一段。最後看符合條件的有幾段,如果大於m段,表明這個x不符合,並且是x小了。所以遞迴的是x到max。

**中的隨機函式是來產生a陣列的,並個數n,段數m都是定義的,也可以改一改變成自己輸出。

#include #include #include #include #include #include #include #include #include #include using namespace std;

#define n 10

#define inf 1000

int judge(int a, int mid, int k)

} if (seg >= k)

return 0;

else

return 1;

}int value(int a, int low, int high, int segment)

}int main()

int m = 3;

cout << endl;

//求出數列中所有數的和,還要求出當中最小的數min

int min = inf, max = 0;

for (int i = 0; i < n && a[i] != ' '; i++)

cout << endl;

int tem = value(a, min, max, m);

cout << tem << endl;

return 0;

}

演算法入門經典第八章學習筆記(上)

教學內容相關章節 8.1演算法分析初步 8.2再談排序與搜尋 8.3遞迴與分治 8.4貪心法 教學目標 加粗表示基本掌握 1 理解 基本操作 漸近時間複雜度的概念和大o記號的含義 2 掌握 最大連續和 問題的各種演算法及其時間複雜度分析 3 正確認識演算法分析的優點和侷限性,能正確使用分析結果 4 ...

演算法競賽入門經典(第八章)

習題8 1 uva1149 11.8 include include using namespace std int main sort w 1,w n 1 l 1 r n num 0 while l r if mi w l 0 l num cout 習題8 2 uva1610 11.8 inclu...

第八章(筆記)

能在 中進行記憶體單元的定址的暫存器只有4個,分別是bx si di bp 其中bx bp 是基址,bx對應的段位址是ds,bp對應的段位址是ss si di 是變址,單獨使用時段位址是ds,組合使用段位址是跟隨組合的基址對應的段位址 中進行記憶體單元定址彙總 si di bx bp 常量 si 常...