上学期看到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了。
原文地址:https://www.cnblogs.com/fjfj/p/9696327.html
时间: 2024-10-20 19:46:06