2018年刑偵科推理試題(C++)
阿新 • • 發佈:2018-09-24
def oid set 算法 mtime abs signed lock c++11
上學期看到2018年刑偵科推理試題,直覺告訴我可以嵌套N層for循環來解答,但後面還是用組合算法窮舉出所有組合算到答案,嵌套太深不好搞啊。
從 0b00000000000000000000
自增到 0b11111111111111111111
,每2bit表示一道題的答案,即: 0b00
為A,0b01
為B,0b10
為C,0b11
為D,
利用位移操作從左邊高位依次讀取每2bit的數,判斷後不符合題意的組合就扔掉,最終肯定有一個組合答案符合。
下面我自己的解法
// // Created by sys234 on 4/3/2018. // #include <vector> #include <iostream> #include <map> #include <ctime> using namespace std; const unsigned int A = 0; const unsigned int B = 1; const unsigned int C = 2; const unsigned int D = 3; vector<unsigned int> getAnswerLine(unsigned int num) { vector<unsigned int> answer; for (unsigned int j = 0; j < 20; j += 2) { //offset 2bit unsigned int x = ((num << (32 - 2 - j)) >> 30); answer.push_back(x); } return answer; } bool isTheSame(int qnum, int qans) { return qnum == qans; } bool notTheSame(int qnum, int qans) { return qnum != qans; } bool isNear(int qans1, int qans2) { return abs(qans1 - qans2) == 1; } unsigned int getAnsAppearTimes(const vector<unsigned int> &alls, int max = -1, bool retAsTimes = false) { map<unsigned int, int> stat; for (auto item : alls) { int val = item; ++stat[val]; } int minAns = 0;//supposing A int qTimes = 0; auto pair1 = stat.find(0); minAns = 0; qTimes = pair1->second; for (int i = 1; i < 4; ++i) { pair1 = stat.find(i); if (qTimes > pair1->second && -1 == max) { minAns = pair1->first; qTimes = pair1->second; continue; } if (qTimes < pair1->second && -1 != max) { minAns = pair1->first; qTimes = pair1->second; continue; } } if (retAsTimes == false) { return minAns; } return qTimes; } unsigned int getAnsNumTimes(const vector<unsigned int> &alls, int max = -1) { return getAnsAppearTimes(alls, max, true); } char echoAns(int n) { switch (n) { case 0: return ‘A‘; case 1: return ‘B‘; case 2: return ‘C‘; case 3: return ‘D‘; default: return ‘\0‘; } } vector<unsigned int> getAnswerLine(unsigned int num); void combination() { unsigned int ansMax = 0b11111111111111111111;//note: 20/2=10 ,2bit presents a answer;A=>00,B=>01,C=>10,D=>11 unsigned int ansMin = 0b0; unsigned int i; for (i = 0; i <= ansMax; ++i) { vector<unsigned int> one = getAnswerLine(i); unsigned int q1 = one[0], q2 = one[1], q3 = one[2], q4 = one[3], q5 = one[4], q6 = one[5], q7 = one[6], q8 = one[7], q9 = one[8], q10 = one[9]; if (q1 == q2 && q1 == q3 && q1 == q4 && q1 == q5 && q1 == q6 && q1 == q7 && q1 == q8 && q1 == q9 && q1 == q10) { //excluding all the same answer continue; } if (isTheSame(q2, A) && notTheSame(q5, C) || isTheSame(q2, B) && notTheSame(q5, D) || isTheSame(q2, C) && notTheSame(q5, A) || isTheSame(q2, D) && notTheSame(q5, B)) { continue; //excluding 2nd } if (isTheSame(q3, A) && isTheSame(q3, q6) || isTheSame(q3, A) && isTheSame(q3, q2) || isTheSame(q3, A) && isTheSame(q3, q4) // || isTheSame(q3, B) && isTheSame(q3, q6) || isTheSame(q3, B) && isTheSame(q6, q2) || isTheSame(q3, B) && isTheSame(q6, q4) // || isTheSame(q3, C) && isTheSame(q3, q2) || isTheSame(q3, C) && isTheSame(q6, q2) || isTheSame(q3, C) && isTheSame(q2, q4) // || isTheSame(q3, D) && isTheSame(q3, q4) || isTheSame(q3, D) && isTheSame(q6, q4) || isTheSame(q3, D) && isTheSame(q2, q4) ) { continue; //excluding 3rd } if (isTheSame(q4, A) && notTheSame(q1, q5) || isTheSame(q4, B) && notTheSame(q2, q7) || isTheSame(q4, C) && notTheSame(q1, q9) || isTheSame(q4, D) && notTheSame(q6, q10)) { continue; //excluding4 } if (isTheSame(q5, A) && notTheSame(q8, A) || isTheSame(q5, B) && notTheSame(q4, B) || isTheSame(q5, C) && notTheSame(q9, C) || isTheSame(q5, D) && notTheSame(q7, D)) { continue; //excluding 5 } if (isTheSame(q6, A) && (notTheSame(q2, q8) || notTheSame(q4, q8)) || isTheSame(q6, B) && (notTheSame(q1, q8) || notTheSame(q6, q8)) || isTheSame(q6, C) && (notTheSame(q3, q8) || notTheSame(q10, q8)) || isTheSame(q6, D) && (notTheSame(q5, q8) || notTheSame(q9, q8)) ) { continue; //excluding 6 } int selectedLeastAlpha = getAnsAppearTimes(one, -1); if (isTheSame(q7, A) && notTheSame(selectedLeastAlpha, C) || isTheSame(q7, B) && notTheSame(selectedLeastAlpha, B) || isTheSame(q7, C) && notTheSame(selectedLeastAlpha, A) || isTheSame(q7, D) && notTheSame(selectedLeastAlpha, D) ) { continue; //excluding 7 } if (isTheSame(q8, A) && isNear(q1, q7) || isTheSame(q8, B) && isNear(q1, q5) || isTheSame(q8, C) && isNear(q1, q2) || isTheSame(q8, D) && isNear(q1, q10) ) { continue; //excluding 8 } if (isTheSame(q9, A) && isTheSame(q1, q6) && isTheSame(q6, q5) || isTheSame(q9, A) && notTheSame(q1, q6) && notTheSame(q6, q5) // || isTheSame(q9, B) && isTheSame(q1, q6) && isTheSame(q10, q5) || isTheSame(q9, B) && notTheSame(q1, q6) && notTheSame(q10, q5) // || isTheSame(q9, C) && isTheSame(q1, q6) && isTheSame(q2, q5) || isTheSame(q9, C) && notTheSame(q1, q6) && notTheSame(q2, q5) // || isTheSame(q9, D) && isTheSame(q1, q6) && isTheSame(q9, q5) || isTheSame(q9, D) && notTheSame(q1, q6) && notTheSame(q9, q5) // ) { continue; //excluding 9th } int optionsCountMax = getAnsNumTimes(one, 1); int optionsCountMin = getAnsNumTimes(one, -1); int diff = optionsCountMax - optionsCountMin; if (isTheSame(q10, A) && 3 != diff || isTheSame(q10, B) && 2 != diff || isTheSame(q10, C) && 4 != diff || isTheSame(q10, D) && 1 != diff ) { continue; //exclusing 10th } //print answer for (int lastAns : one) { cout << echoAns(lastAns)<<" "; } cout << endl; } } int main() { std::cout << clock() << std::endl; combination(); std::cout << clock() << std::endl; return 0; }
解題中少了幾個過濾條件,打印除算出好幾行答案,差點以為我解法寫錯了,然後搜索到其他網友的答案,提有意思了,有嵌套多層for循環生成組合的。
有用4進制組合答案,多種語言好多技巧,學習了...
最終把缺少過濾條件判斷加上去就OK了。
2018年刑偵科推理試題(C++)