###### 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);
}
```