小米 OJ 賽題——高弗雷勳爵(2018年09月13日 17:30 ~ 19:00)
阿新 • • 發佈:2018-12-09
題目描述
第七軍團的據點有數不清的敵人,高弗雷拿著一把附魔火槍,射出的子彈會在敵人間跳躍,一發子彈就能對所有敵人造成 2 點傷害,如果該子彈導致了任意敵人死亡(即血量小於等於 0),該子彈還會再次對所有敵人造成2點傷害,直到沒有新的敵人死亡為止。那麼,高弗雷需要打出幾顆子彈才能消滅所有敵人呢?
要求
輸入
- 輸入是每個敵人的血量,用空格分開,回車結束。0<敵人的數量<=10000; 0<敵人的血量<=10^9
輸出
- 輸出是一個數字,是高弗雷最少需要打出的子彈的個數
- 輸出內容為只出現過唯一一次的數字
樣例
- 輸入樣例:1 12 3 6 10
- 輸出樣例:2
- 輸入樣例:44 55 66 77 99 88
- 輸出樣例:45
- 輸入樣例:19 18 17 14 16 15 13 11 12 20
- 輸出樣例:6
- 輸入樣例:28 12 30 25 14 18 27 16 25 11 20
- 輸出樣例:8
解題
初始程式碼:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stddef.h> #include <ctype.h> #define BUFFERSIZE 1000000 int main() { char line[1000001]; // 迴圈讀入多行資料 while (scanf("%s", &line) != EOF) { // 處理並輸出結果,務必輸出換行符 // printf("%d\n", ans); } return 0; }
第一步,獲取字串輸出,使用 fgets 函式替代 gets 函式獲取一整行輸入。fgets 函式與 gets 函式的不同在於 fegts 可以通過第二個引數來限制讀入字元數來解決溢位問題。
while (fgets(line, BUFFERSIZE, stdin))
{
int i = 0; // 迴圈計數
int c = 0; // 子字串個數計數
char **arr = NULL; // 指向動態二維字元陣列的指標
c = split(line, ' ', &arr);
}
第二步,設計字串處理函式,將字串拆分成二維字元陣列。
// 功能:將字串按照某個字元分割成多個子字串,返回該組子串的集合 // 引數 1 :源字串 // 引數 2 : 間隔字元 // 引數 3 : 儲存子字串的二維數字的地址 int split(char *str, char c, char ***arr) { int count = 1; // 拆分後字串的個數 int token_len = 1; // 單個字串的長度 int i = 0; char *p; char *t; // 判斷要拆分成多少個子串 p = str; while (*p != '\0') { if (*p == c) count++; p++; } // 申請 count 個指標單元 *arr = (char **)malloc(sizeof(char *) * count); if (*arr == NULL) exit(1); // 為每個指標單元申請 token_len 長度的空間 p = str; while (*p != '\0') { if (*p == c) { (*arr)[i] = (char *)malloc(sizeof(char) * token_len); if ((*arr)[i] == NULL) exit(1); token_len = 0; i++; } p++; token_len++; } // 迴圈到最後一個字元時,跳出了迴圈,單獨為最後一個子串申請空間 (*arr)[i] = (char *)malloc(sizeof(char) * token_len); if ((*arr)[i] == NULL) exit(1); // 為動態分配的二維陣列第二維賦值 i = 0; p = str; t = ((*arr)[i]); while (*p != '\0') { if (*p != c && *p != '\0') { *t = *p; t++; } else { *t = '\0'; i++; t = ((*arr)[i]); } p++; } // 遍歷到最後一個字元時,單獨加結束符 *t = '\0'; // 避免野指標 p = t = NULL; return count; }
未完待續,會繼續更新完整!