題目傳送門
<==戳這
本題最重要的乙個問題:如何分辨 全對,半對,錯誤 這三種答題情況。
不妨這樣想:令 a =2^
0,b =2^
1,c =2^
2, d=2^
3,e=2^
4即如果選擇的是a,那麼該同學這道題的答案是1
如果選擇的是 a ,c 那麼該同學這道題的答案是 1+4
=5
為什麼要這麼處理?
位運算子 : ^ 異或運算子 (二進位制位相同為0,不同為1)
| 按位異或運算子 (二進位制位有1則為1,都是0則為0)
& 按位與運算子 (二進位制位有0則為0,都為1才是1)
那麼如果正確答案是 a,c 而同學選擇的是 a,b。
即正確答案是:5 ,同學的答案是3
(轉化為二進位制)即:101 和 011
, 那麼5^1
==110
(二進位制),記為sign=5^
1那麼我們就可以知道,如果異或運算之後,某一位是0,說明該選項正確,而如果是1,說明該選項錯誤或者沒選
如何判斷全對:
我們將該題的正確選項按照上述方法轉化後存入陣列trueres[maxn]內
然後,將這道題的正確答案,和,該同學這道題選擇的答案進行「異或運算」操作
如果該同學全對的話,操作後為0,否則說明沒有全對
比如上面舉的例子:正確答案:101,同學的答案:011 ,異或運算結果不為0,說明沒有全對
如果部分正確:
我們將正確答案和同學的答案進行「按位或」操作(|),
如果同學的答案沒有選全,且沒有選錯,那麼操作之後的結果還是等於正確答案。
比如這道題:正確答案:101,同學的答案:011,按位異或運算的結果為:111
!=正確答案
說明同學選擇的選項中有錯誤選項。
而如果同學只選了a選項,即答案為:001,那麼按位異或運算的結果是101
==正確答案
說明同學沒有選全,並且沒有錯誤選項
接下來,我們用陣列 res [5]
= 代表 a ~ e 。列舉k=0~
5(即選項a ~ e)再對上述異或運算後的值sign進行「按位與」操作,即 & 操作
我們上面說過,sign中如果某一位有1,說明該選項錯誤或者沒選,所以我們可以通過
按位與操作來判斷sign中某一位是否為1
sign=
110k==
0 res[k]=1
(001
),sign & res[k]
==000
==>a選項正確
k==1 res[k]=2
(010
),sign & res[k]
==010
==>b選項錯誤
k==2 res[k]=2
(100
),sign & res[k]
==100
==>c選項錯誤(沒選也算錯誤)
解決掉上述關鍵問題,下面我們只需要記錄下:每道題每個選項的錯誤次數,每個同學的得分即可
#include
#include
#include
using
namespace std;
int n,m,optnum,truenum,temp,maxcnt;
//人數,題目數,題目總選項個數,正確答案選項個數,錯誤最大次數
int res[5]
=,ans[
1005][
105]
;//res上面說過,ans記錄第 i 位同學的第 j 題的答案
intmain()
}for
(int i=
0; i)int sign=ans[i]
[j]^trueres[j]
;//判斷是否全對
if(sign==0)
else
for(
int k=
0; k<
5; k++)}
}}printf
("%.1f\n"
,grade);}
for(
int i=
0; iif(maxcnt==
0) cout<<
"too ******\n"
;else}}
}}
PAT 1073 多選題常見計分法
描述 批改多選題是比較麻煩的事情,有很多不同的計分方法。有一種最常見的計分方法是 如果考生 選擇了部分正確選項,並且沒有選擇任何錯誤選項,則得到50 分數 如果考生選擇了任何乙個錯 誤的選項,則不能得分。本題就請你寫個程式幫助老師批改多選題,並且指出哪道題的哪個選項 錯的人最多。輸入 輸入在第一行給...
PAT1073 多選題常見計分法 (20 分)
題目 坑點 include include include using namespace std struct st int nu 5 int ma pr 105 bool cmp struct st a,struct st b void solve pr i id i 1 pr i ma 0 w...
1073 多選題常見計分法
批改多選題是比較麻煩的事情,有很多不同的計分方法。有一種最常見的計分方法是 如果考生選擇了部分正確選項,並且沒有選擇任何錯誤選項,則得到50 分數 如果考生選擇了任何乙個錯誤的選項,則不能得分。本題就請你寫個程式幫助老師批改多選題,並且指出哪道題的哪個選項錯的人最多。輸入格式 輸入在第一行給出兩個正...