貪婪演算法
Greedy Algorithm
林芊妘
常見演算法
分治法
貪婪法
動態規劃
回溯法
分支定界法
✔
✔

週四的演算法放課會教喔
分治法-n階層
Divide and Conquer
分治法:將問題拆分為獨立子問題,遞迴求解後合併
9!=9x8x7x6x5x4x3x2x1
8!=8x7x6x5x4x3x2x1
7!=7x6x5x4x3x2x1
6!=6x5x4x3x2x1
5!=5x4x3x2x1
自訂函數f(n)為n階層
可推論f(n)=n*f(n-1)
Divide:大問題f(n)切割成小問題f(n-1),
直到切割成f(1),f(1)答案就是1
Conquer:將f(n-1)的結果乘以n就可以獲得f(n)的結果
貪婪法-找零問題
Greedy
貪婪法:每步選擇當前最優解,不回溯檢查
🍫
32元
💰
50元
➡️
🪙
1
1元x18
找零會以幣額較大的優先給客人
(假設幣值50、10、5、1)
➡️
🪙
🪙
🪙
🪙
🪙
10
5
1
1
1
問題
子問題
子問題
子問題
+ +
局部最佳解
最佳解
動態規劃-找零問題
Dynamic Programming
動態規劃:適用於重疊子問題,透過記憶化避免重複計算
🍫
32元
💰
50元
如果有幣值9元
➡️
🪙
🪙
🪙
🪙
🪙
10
5
1
1
1
🪙
9
🪙
9
➡️
*不適用貪婪法
動態規劃-找零問題
Dynamic Programming
動態規劃:適用於重疊子問題,透過記憶化避免重複計算
問題
子問題
子問題
+ +
最佳解
找規律
子問題
紀錄子問題答案
查表
最少硬幣湊出18元
最少硬幣湊出17元、13元、9元、8元
(假設幣值50、10、9、5、1)
回溯法-八皇后問題
Backtracking
回溯法:窮舉所有可能,遇到不符合條件則回退
分支定界法
Branch and Bound
分支界限法:窮舉+剪枝,用界限函數排除無效解。

刪數字
給定一個數字num;
刪除其中k個數;
求最小的結果
刪數字
刪數字🌰
num=15726
k=2
1 5 7 2 6
126
刪數字🌰
num=528163579
k=4
528163579
13579
刪數字-觀念
- 小的數字在前
- 大的數字在後
126
162
<
162
*前面數字比後面數字大時刪除
刪數字-觀念
- 小的數字在前
- 大的數字在後
126
162
<
162
*前面數字比後面數字大時刪除
num=23159
k=3
23159
刪數字🌰
num=23159
k=3
23159
刪數字🌰
num=23159
k=3
23159
刪數字🌰
num=23159
k=3
23159
刪數字🌰
num=23159
k=3
23159
刪數字🌰
15
刪數字-stack
2
9
3
1
5
刪數字-stack
2
9
3
1
5
刪數字-stack
2
9
3
1
5
刪數字-stack
9
1
5
刪數字-stack
9
1
5
刪數字-stack
9
1
5
刪數字-stack
9
1
5
刪數字-stack
1
5
vector
| index | 0 | 1 | 2 | 3 | 4 |
| 內容 | 1 | 3 | 5 | 7 |
.size()
.begin()
.end()
.back()
刪數字-程式碼
主程式
int main()
{
string num;
int k;
cin>>num>>k;
string result=del(num,k);
cout<<result;
return 0;
}刪數字-程式碼
函式del(num, k)
string del(string num,int k){
vector<char>s;
for(int i=0;i<num.size();i++){
char n=num[i];
while(!s.empty()&&s.back()>n&&k>0){
s.pop_back();
k--;
}
s.push_back(n);
}
while(k>0&&!s.empty()){
s.pop_back();
k--;
}
string result(s.begin(),s.end());
return result;
}刪數字-程式碼
函式del(num, k)
string del(string num,int k){
vector<char>s;
for(int i=0;i<num.size();i++){
char n=num[i];
while(!s.empty()&&s.back()>n&&k>0){
s.pop_back();
k--;
}
s.push_back(n);
}
while(k>0&&!s.empty()){
s.pop_back();
k--;
}
string result(s.begin(),s.end());
return result;
}#include <bits/stdc++.h>
using namespace std;
string del(string num,int k){
vector<char>s;
for(int i=0;i<num.size();i++){
char n=num[i];
while(!s.empty()&&s.back()>n&&k>0){
s.pop_back();
k--;
}
s.push_back(n);
}
while(k>0&&!s.empty()){
s.pop_back();
k--;
}
string result(s.begin(),s.end());
return result;
}
int main(){
string num;
int k;
cin>>num>>k;
string result=del(num,k);
cout<<result;
return 0;
}手續費
Priority Queue
最大的優先取出priority_queue<int>(預設)
最小的優先取出priority_queue<int,vector<int>,greater<int> >

#include <bits/stdc++.h>
using namespace std;
int main()
{
priority_queue<int> pq1;
priority_queue<int,vector<int>,greater<int> > pq2;
pq1.push(6);
pq1.push(3);
pq1.push(9);
while(!pq1.empty())
{
cout << pq1.top();
pq1.pop();
}
cout<<endl;
pq2.push(6);
pq2.push(3);
pq2.push(9);
while(!pq2.empty())
{
cout << pq2.top();
pq2.pop();
}
return 0;
}963
369


#include <bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int> > pq;
int main(){
int n,point;
long long money=0;
cin>>n;
while(!pq.empty()) pq.pop();
for(int i=0;i<n;i++){
cin>>point;
pq.push(point);
}
while(1){
int a,b;
a=pq.top();
pq.pop();
b=pq.top();
pq.pop();
money+=a+b;
pq.push(a+b);
if (pq.size()==1) break;
}
cout<<money<<endl;
}貪婪演算法
By chainy
貪婪演算法
- 145