Review

Stack&Queue

一業 葉子齊

stack

queue

- 引入函式庫<stack>

- 先進來 後出去

- 引入函式庫<queue>

- 先進來 先出去

stack

queue

push

pop

top

push

pop

front

stack 功能
push(x) 放入元素
pop() 刪除第一個元素
top() 讀取最上面的元素
empty() 是否為空
size() 內有幾個元素
queue 功能
push(x) 放入元素
pop() 刪除第一個元素
front() 讀取最前面的元素
empty() 是否為空
size() 內有幾個元素

宣告

stack/queue<型態>名稱;

stack

queue

stack<int>SK;
queue<int>QE;

SK

QE

stack

queue

SK.push(A);

QE.push(A);

A

A

SK

QE

stack

queue

SK.push(B);

QE.push(B);

A

A

SK

QE

B

B

stack

queue

SK.push(C);

QE.push(C);

A

SK

QE

B

C

B

A

C

top

front

stack

queue

SK.pop();

QE.pop();

A

SK

QE

B

C

A

B

C

front

stack

queue

SK.pop();

QE.pop();

A

SK

QE

B

C

C

C

B

front

stack

queue

SK.pop();

A

SK

QE

B

C

C

C

front

stack

queue

A

SK

QE

B

C

C

C

empty

是空的 → 回傳1

不是空的(內含元素)→ 回傳0

回傳 1

回傳 0

stack

queue

A

SK

QE

B

C

C

A

B

size

內有幾個元素

回傳 0

回傳 2

判斷是否為空

(回傳) 空的 不是空的
empty 1 0
size 0 內含元素的數量

判斷是否為空

(回傳) 空的 不是空的
empty 1 0
size 0 內含元素的數量

練習題

輸入說明:第一行有一個 N(1≤N≤10^5) ,

接下來有 N 行,每一行一開始有一個 k ,代表哪一種操作:


如果 k=1 ,
請再讀入一個整數 x(1≤x≤109) ,並在堆疊頂端加入該整數。

如果 k=2 ,
請輸出堆疊最頂端的元素,
如果當前堆疊內沒有元素,請輸出 −1 。


如果 k=3 ,
請刪除堆疊最頂端的元素,
如果當前堆疊內沒有元素,請無視該操作。

範例輸入:

13

1 1

1 2

1 3

2

3

3

2

1 4

3

2

3

3

2

 

範例輸出:

3

1

1

-1

#include <iostream>
#include <stack>

using namespace std;
int main()
{
    int n,k,a;cin>>n;
    stack<int>s;
    
    for(int i=0;i<n;i++){
        cin>>k;
        
        if(k==1){
            cin>>a;
            s.push(a);
        }
        
        else if(k==2){
            if(s.size()==0){
                cout<<"-1"<<endl;
            }
            else if(s.size()!=0){
                cout<<s.top()<<endl;
            }
        }
        
        else if(k==3 && s.size()!=0){
                s.pop();
            
        }
    }

    return 0;
}

加速程式

ios_base::sync_with_stdio(0);
cin.tie(0);

打在int main()大括號裡

Dynamic Programming

一群 林芊妘

Dynamic Programming  動態規劃

把大問題化成小問題,並且用陣列儲存起來

範例-費氏數列

f(0) f(1) f(2) f(3) f(4) f(5)
0 1 1 2 3 5
f(6) f(7) f(8) f(9) f(10) f(11)
8 13 21 34 55 89

=>  f(n)  =  f(n-1)  +  f(n-2)

範例-費氏數列

using namespace std;
#include <iostream>

int f(int num)
{
    if (num==0) return 0;
    else if (num==1) return 1;
    else
    {
        int fib=f(num-1)+f(num-2);
        return fib;
    }
}

int main()
{
    int n;
    cin>>n;
    cout<<f(n);
    
    return 0;
}

ERROR

範例-費氏數列

f(5)

f(3)

f(3)

f(4)

f(2)

f(2)

f(1)

範例-費氏數列

using namespace std;
#include <iostream>

long long f(long long num)
{
    long long dp[num+1];
    dp[0]=0;
    dp[1]=1;
    for(int i=2;i<num+1;++i)
    {
        dp[i]=dp[i-1]+dp[i-2];
    }
    return dp[num];
}

int main()
{
    int num;
    cin>>num;
    cout<<f(num);
    
    return 0;
}

範例-最短行徑

0    1    3    3

2    3    1    0

3     1    2    0

範例-最短行徑

1

1

1

4

3

1

1

1

0

2

3

4

6

10

10

20

範例-最短行徑

0    1    3    1

2    3    0    4

3     2    2    0

範例-最短行徑

0    1    3    1

2    3    0    4

3     2    2    0

範例-最短行徑

0    1    4    5

2    3    0    4

3     2    2    0

範例-最短行徑

0    1    4    5

2    3    0    4

5     2    2    0

範例-最短行徑

0    1    4    5

2    3    0    4

5     2    2    0

範例-最短行徑

0    1    4    5

2    4    0    4

5     2    2    0

範例-最短行徑

0    1    4    5

2    4    0    4

5     2    2    0

範例-最短行徑

0    1    4    5

2    4    0    4

5     6    2    0

範例-最短行徑

0    1    4    5

2    4    0    4

5     6    2    0

範例-最短行徑

0    1    4    5

2    4    4    4

5     6    2    0

範例-最短行徑

0    1    4    5

2    4    4    4

5     6    2    0

範例-最短行徑

0    1    4    5

2    4    4    4

5     6    6    0

範例-最短行徑

0    1    4    5

2    4    4    4

5     6    6    0

範例-最短行徑

0    1    4    5

2    4    4    8

5     6    6    0

範例-最短行徑

0    1    4    5

2    4    4    8

5     6    6    0

範例-最短行徑

0    1    4    5

2    4    4    8

5     6    6    6

範例-最短行徑

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int m,n;
    cin>>m>>n;
    int path[m][n];
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++) 
            cin>>path[i][j];
            //輸入數值
    }
    for(int i=1;i<n;i++)
        path[0][i]+=path[0][i-1]; //累加最上橫排
        
    for(int i=1;i<m;i++)
        path[i][0]+=path[i-1][0]; //累加最左直排
        
    for(int i=1;i<m;i++)
    {
        for(int j=1;j<n;j++)
        {
            path[i][j]+=min(path[i-1][j],path[i][j-1]); 
            //找上方和左方的最小值並相加
        }
    }
    cout<<path[m-1][n-1]<<endl;

    return 0;
}

爬樓梯

今天有個屁孩小明,他爬階梯時可以一次爬一格、三格或是五格,他們學校每半層樓梯有11格,請問他爬到4樓有幾種方法?

爬樓梯

#include <iostream>
using namespace std;
int dp[1000];

int main()
{
    int step[3]={1,3,5};
    dp[0]=1;
    for(int i=0;i<3;i++)
    {
        for(int j=step[i];j<1000;j++)
            dp[j]+=dp[j-step[i]];
    }        
    int n=11,a=1;
    for(int i=0;i<8;i++)
        a*=dp[n];
    
    cout<<a<<endl;


    return 0;
}

Structure 

一仁 蔡其霏

什麼是 structure?

儲存很多個int / char                陣列

but…

要儲存一個int  和一個char 呢?     

甚至...是要儲存陣列?

 

structure

structure是一種 "資料形態"

可以將不同的資料

形態同時儲存

例如~~ 宣告

#include <iostream>
using namespace std;

struct checkup{
    string name;
    double height; 
    int weight;
    double eyesight[2];
    void BMI(){
        cout << weight/(height*height) << endl;
    }
}student1;
int main(){
}

(宣告在主程式之外)

~~賦值

#include <iostream>
using namespace std;

struct checkup{
    string name;
    double height; 
    int weight;
    double eyesight[2];
    void BMI(){
        cout << weight/(height^2) << endl;
    }
};
int main(){
    checkup student3={
        .name="Phoebe",
        .height=1.88,
        .weight=70,
        .eyesight[0] = 1.0;
        .eyesight[1] = 1.2;
    };
    
	checkup student2={"Phoebe", 1.88, 70, 1.0, 1.2};
    
    cin >> student1.name;
	cout << "姓名" << student1.name << endl;

	student2.BMI();
}

也可以這樣^ ^

ps. 這邊.name 後面不用加()

()是函式才要加的

struct也可以用陣列

Grade student[3]={
  {.name="aa", .height = 150,},
  {.name="bb", .height = 160,},
  {.name="cc", .height = 170,},
    };

struct也可以放在struct裡

struct identity{
    int id;
    string name;
};
 
struct checkup{
    identity stu;
    int height;
    int weight;
    int eyesight[2];
};

typedef : 取綽號

typedef struct checkup{
    string name;
    int height; 
    int weight;
    int eyesight[2],
    void BMI{
        cout << weight/(height^2) << endl;
}check;

假設你是🍁資的總務,你要做一個今年社團的支出表!


假設收入10000,有n個項目,請分別輸入支出的項目、相應金額以及是否已經報銷(bool)。最後輸出剩餘的金額(bool = 1)

Quiz

測資

5

食物 1500 1 

場地租金  2000  0 

獎品 800 0

交通費 300 1

傳單 700  1 

 

ans:

剩餘  7500

Ans

#include <iostream>
#include <string>
using namespace std;

// 定義支出項目結構
struct expenditure {
    string item;
    int amount;
    bool pay;
}expend[100];// 創建支出項目陣列

int main() {
    int income = 10000; // 收入
    int numItems; //支出項目數量
    cin >> numItems;

    // 輸入支出項目資料
    for (int i = 0; i < numItems; i++) {
        cin >> expend[i].item >> expend[i].amount >> expend[i].pay;
    }

    // 計算總支出
    int total = 0l;
    for (int i = 0; i < numItems; i++) {
        if (expend[i].pay) {
            total += expend[i].amount;
        }
    }
  
    // 輸出剩餘金額
    cout << "剩餘 " << income - total << endl;
    return 0;
}

End~

Binary Search

一忠 陳芊邑

二分搜

還記得之前聊過的終級密碼嗎?

二分搜

不斷取中間值直到取到答案為止

二分搜

65

1

100

紅色的線「不合法」,藍色的線「合法」

我們要找到藍色線的最左端

二分搜

51

1

100

[51,100]

二分搜

51

1

100

[51,74]

74

二分搜

51

1

100

[62,74]

74

62

二分搜

51

1

100

[62,67]

74

62

67

二分搜

51

1

100

[64,67]

74

62

67

64

二分搜

67

62

74

[65]

64

65

二分搜 

這樣就結束了嗎?

怎麼可能

接下來要講解範例 

給你一個嚴格遞增的數列A1,A2,A3.....An,

&下面有幾個問題的詢問數k,

以及k個詢問的整數x,

求數列中是否存在一個Ai(1<=i<=n)的值與X相等?

二分搜

#include <bits/stdc++.h>
using namespace std;

int bs(int arr[], int n, int ans) {
    int left = 1;
    int right = n;//數組長度

    while (left <= right) {
        int mid = (left + right) / 2;

        if (arr[mid] == ans) {
            return mid; // 返回找到的索引
        } else if (arr[mid] < ans) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    return 0; // 找不到則返回0
}

int main() {
    int n, k;
    cin >> n >> k;

    int arr[n];
    for (int i = 1; i <= n; ++i) {
        cin >> arr[i];
    }

    for (int i = 0; i < k; ++i) {
        int x;
        cin >> x;

        int ans = bs(arr, n, x);
        cout << ans << endl;
    }

    return 0;
}

二分搜

它看起來好像有個固定模式?
那來看個模板好了

二分搜-模板

left = 左界
right = 右界
while (左比右小,代表邊界還正常) {
  mid = 左右邊界的中間點
  if (數列中間點的數值大於 ans) {
    右半邊可以不用看,把右界移到中間(mid)
  } else if (數列中間點的數值小於 ans) {
    左半邊可以不用看,把左界移到中間(mid)
  } else {
    找到答案
  }
}

二分搜-實作細節

  • 記得排序

  • 確認區間定義、範圍

  • 左右界如何改變

  • 負數除法會有問題, 改用 left+(right-left)/2

二分搜

看起來很簡單?很少?

 對,我們還有一題範例

要將n個士兵升等,

每人升x等需x^2金幣,

現有c枚金幣,問全體最少可到幾等

 

範例1說明:將第1位由2升至5需3^2金幣,第2位由4升至5需1^2金幣,全體最少有5級

輸入說明:

第1行有兩個正整數N或C,分別士兵數及金幣數
第2行有N個正整數a1~an

代表N個士兵目前的等級,皆以空白隔開

 

輸出說明:

請輸出一行正整數U,表示最少可全部升至U級(含)以上

沒錯,這題的解決方法就是二分搜
直接搜尋目標的等級,
計算此等級以下的士兵升等
是否超出金幣預算
#include <bits/stdc++.h>
using namespace std;
long long level[2000000],n;
long long x(long long lv){
  //計算到等級lv所需要的錢
long long sum=0;
  for(long long i=0;i<n;i++){
    if(level[i]<lv){
      //如果士兵等級<lv
      sum=sum+(level[i]-lv)*(level[i]-lv);
      //計算每個士兵的花費並加總
    }
}
  return sum;
  //返回預算

}
int main(){

  long long c;
  long long l=1,r=2000000;
  cin>>n>>c;
  for(long long i=0;i<n;i++){
    cin>>level[i];
  }
  while(l<=r){
    //左閉右閉,使用等於搜索全部範圍
    long long mid=l+(r-l)/2;
    //預期的等級mid
    if(x(mid)>c){
      r=mid-1;
  }
    else{
      l=mid+1;
    }
}
 cout<<r<<endl;//如果未找到精確值,輸出低於預算的最接近等級
}

自由練習!

review

By chainy

review

  • 143