---
# System prepended metadata

title: 書本的位置(Public)
tags: [計概詳解]

---

###### tags: `計概詳解`
# 書本的位置(Public)
圖書館有 n 排書架，第 1 排有 a1 本書，編號依次為 1, 2,..., a1 ；
第 2 排有 a2 本書，編號依次為 a1+1, a1+2,... ,a1+a2；
依次類推，最後一本書的編號為 a1+a2+...+an。

現已知書本編號 b1,... , bm ，要找出這些書本所在的排數。

## 解題思維
請參考老師的解說影片：i-learning/開始上課/2021-課程內容/N13-單元四作業講解

### 解法1：暴力破解法
 建表<code>table[]</code>紀錄每一本書在第幾排，取得書本編號b之後，直接查表<code>table[b]</code>就知道書在第幾排。
 https://youtu.be/msZnK_QbB-0
### 程式碼1
```c=
#include <stdio.h>

#define N 100000 //假設書本不超過100000萬本

int main()
{
    int table[N];//建表
    int n, a, m, b;
    int cnt = 0;//表示正在處理編號cnt的書。
    
    scanf("%d", &n);//讀取 n(圖書館有n排書架)
    for (int i=1; i<=n; i++){//重複n次
        scanf("%d", &a);//讀取一個a
        for (int j=0; j<a; j++){//連續a本書都設定成第i排
            table[++cnt] = i;
        }
    }
	
    scanf("%d", &m);//讀取m
    for (int i=0; i<m; i++){//重複處理m本書
        scanf("%d", &b);//讀取一個b
        printf("%d\n", table[b]);//輸出查表結果
    }
    return 0;
}
```


### 解法2：線性解
記每一排最後一本書的編號，找第一個超過書本b的那一排。
https://youtu.be/gPcD6w4EGm8
### 程式碼2
```c=
/*線性解*/
#include <stdio.h>

int main()
{
    int n, m, k;
    scanf("%d", &n);
    int r[n+1];
    r[0] = 0;
    for (int i=1; i<=n; i++){
        scanf("%d", &k);
        r[i] = r[i-1] + k;
    }
    scanf("%d", &m);
    for (int i=0; i<m; i++){
        scanf("%d", &k);
        int row=1;
        while(r[row] < k) row++;
        printf("%d\n", row);
    }
    return 0;
}
```

### 解法3：二分搜尋法
記每一排最後一本書的編號，找第一個超過書本b的那一排。
使用二分搜尋法來找第幾排，可以加快運算速度。
https://youtu.be/hGdIvob4xjg

### 程式碼3
```c=
/*二分搜尋法*/
#include <stdio.h>

int bsearch(int r[], int start, int end, int k);
int main()
{
    int n, m, k;
    scanf("%d", &n);
    int r[n+1];
    r[0] = 0;
    for (int i=1; i<=n; i++){
        scanf("%d", &k);
        r[i] = r[i-1] + k;
    }
    scanf("%d", &m);
    for (int i=0; i<m; i++){
        scanf("%d", &k);
        printf("%d\n", bsearch(r, 1, n, k));
    }
    return 0;
}

int bsearch(int r[], int start, int end, int k)
{
    int mid=(start+end)/2;
    if (r[mid]>=k && r[mid-1]<k) return mid;
    if (r[mid] < k) return bsearch(r, mid+1, end, k);
    return bsearch(r, start, mid-1, k);
}
```