1. 程式人生 > >2018年刑偵科推理試題(C++)

2018年刑偵科推理試題(C++)

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++)