原題: https://www.patest.cn/contests/pat-b-practise/1058
思路: 本題主要就是怎么讀取數據的問題, 一定要注意scanf函數匹配到
空格或者回車會結束當前變量的賦值, 并且會丟棄這個空格或回車.
關于如何判斷一項答題是否正確, 可以采用循環一個一個判斷, 也可拼成
字符串用strcmp來判斷. 我一開始使用的是累加和來判斷是否正確, 但是
這種方法最后一個測試點通不過. 因為abcde的ASCII碼分別是,
97 98 99 100 101, 那么97+101 = 98+100. 后來我看了一位網友的方案
采用累加或的方法, 完美解決了這種值不一樣和確一樣的問題.
首先把abcde, 分別轉成12345, 分別表示成1的2進制左移
1 << 1 == 10
1 << 2 == 100
1 << 3 == 1000
1 << 4 == 10000
1 << 5 == 100000
加入一個選項是abcd為正確, abcd進行或運算則為1110, 這樣就不會出現和
重復的問題. 在后面比較的時候, 直接判斷值是否相等即可得知是否正確.
并且假如某個學生就是抽風, 正確答案是abc, 但是他的答案是bca, 像這種
極端的答案如果用傳統的方法判斷, 搞不好還得先來遍排序, 但是用2進制的
方法, 不存在這個問題.
實現:
#include <stdio.h>struct Ques {int fscore; // 該題分數int calc; // 正確計算分int wnum; // 該題錯誤次數
};
typedef struct Ques ques;int main (void) {int snum; // 學生人數int qnum; // 題目數量ques qmsg[100]; // 每一題的信息int useless; // 沒用的東西int rnum; // 正確選項個數int i;int j;int k;char ch;scanf("%d %d", &snum, &qnum);for (i = 1; i <= qnum; i++) {qmsg[i].calc = 0;qmsg[i].wnum = 0;scanf("%d %d %d", &qmsg[i].fscore, &useless, &rnum);for (j = 1; j <= rnum; j++) {// 這里需要匹配空格scanf(" %c", &ch);// qmsg[i].calc += ch;qmsg[i].calc |= 1 << (ch - 'a' + 1);}// printf("qmsg[i].calc: %d\n", qmsg[i].calc);}getchar(); // 去除回車int score; // 學生得分int tcalc = 0; // 臨時計算分int cnum; // 選中選項個數char ch2; // 臨時用for (i = 1; i <= snum; i++) {score = 0;j = 1; // 題目編號// 每次遍歷一整行, 為一個學生的答題信息// 檢測到(, 即答到了下一題while ((ch = getchar()) != '\n') {if (ch == '(') {scanf("%d", &cnum);for (k = 1; k <= cnum; k++) {scanf(" %c", &ch2);// tcalc += ch2;tcalc |= 1 << (ch2 - 'a' + 1);}if (tcalc == qmsg[j].calc) {score += qmsg[j].fscore;} else {qmsg[j].wnum += 1;}tcalc = 0;j++;}}printf("%d\n", score);}int wmax = qmsg[1].wnum;for (i = 1; i <= qnum; i++) {if (qmsg[i].wnum > wmax) {wmax = qmsg[i].wnum;}}if (wmax == 0) {printf("Too simple\n");} else {printf("%d", wmax);for (i = 1; i <= qnum; i++) {if (qmsg[i].wnum == wmax) {// 每個空格都很關鍵printf(" %d", i, ch);}}}return 0;
}
參考: http://www.jianshu.com/p/4a8a570e41c3