Project Euler 185

Project Euler 185

题目

Number Mind

The game Number Mind is a variant of the well known game Master Mind.

Instead of coloured pegs, you have to guess a secret sequence of digits. After each guess you're only told in how many places you've guessed the correct digit. So, if the sequence was \(1234\) and you guessed \(2036\), you'd be told that you have one correct digit; however, you would NOT be told that you also have another digit in the wrong place.

For instance, given the following guesses for a \(5\)-digit secret sequence,

90342 ;2 correct
70794 ;0 correct
39458 ;2 correct
34109 ;1 correct
51545 ;2 correct
12531 ;1 correct

The correct sequence \(39542\) is unique.

Based on the following guesses,

5616185650518293 ;2 correct
3847439647293047 ;1 correct
5855462940810587 ;3 correct
9742855507068353 ;3 correct
4296849643607543 ;3 correct
3174248439465858 ;1 correct
4513559094146117 ;2 correct
7890971548908067 ;3 correct
8157356344118483 ;1 correct
2615250744386899 ;2 correct
8690095851526254 ;3 correct
6375711915077050 ;1 correct
6913859173121360 ;1 correct
6442889055042768 ;2 correct
2321386104303845 ;0 correct
2326509471271448 ;2 correct
5251583379644322 ;2 correct
1748270476758276 ;3 correct
4895722652190306 ;1 correct
3041631117224635 ;3 correct
1841236454324589 ;3 correct
2659862637316867 ;2 correct

Find the unique 16-digit secret sequence.

解决方案

本代码基于深度优先搜索寻找答案,枚举的内容是枚举线索中“未确定的正确数位组合”。实现时,使用了嵌套DFS。外层的DFS用于搜索每个线索;内层DFS属于组合枚举,用于寻找“未确定的正确数位组合”。

使用的优化如下:

  1. 将每条线索基于正确数量从小到大排序,避免一开始枚举组合的数量过大。
  2. 如果遍历到某条线索,发现正确数量太多,那么及时返回。
  3. 枚举某条线索的“未确定的正确数位组合”时,忽略那些目前是错误的或者是已经填数的数位。

本题也可以使用meet-in-the-middle思想,或者是模拟退火算法完成。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# include <bits/stdc++.h>
using namespace std;
const int N = 22;
const int M = 16;
const int D = 10;
int vis[M][D] = {0};
int tmp[M];
int A[N][M] = {
{2, 3, 2, 1, 3, 8, 6, 1, 0, 4, 3, 0, 3, 8, 4, 5},
{3, 8, 4, 7, 4, 3, 9, 6, 4, 7, 2, 9, 3, 0, 4, 7},
{3, 1, 7, 4, 2, 4, 8, 4, 3, 9, 4, 6, 5, 8, 5, 8},
{8, 1, 5, 7, 3, 5, 6, 3, 4, 4, 1, 1, 8, 4, 8, 3},
{6, 3, 7, 5, 7, 1, 1, 9, 1, 5, 0, 7, 7, 0, 5, 0},
{6, 9, 1, 3, 8, 5, 9, 1, 7, 3, 1, 2, 1, 3, 6, 0},
{4, 8, 9, 5, 7, 2, 2, 6, 5, 2, 1, 9, 0, 3, 0, 6},
{5, 6, 1, 6, 1, 8, 5, 6, 5, 0, 5, 1, 8, 2, 9, 3},
{4, 5, 1, 3, 5, 5, 9, 0, 9, 4, 1, 4, 6, 1, 1, 7},
{2, 6, 1, 5, 2, 5, 0, 7, 4, 4, 3, 8, 6, 8, 9, 9},
{6, 4, 4, 2, 8, 8, 9, 0, 5, 5, 0, 4, 2, 7, 6, 8},
{2, 3, 2, 6, 5, 0, 9, 4, 7, 1, 2, 7, 1, 4, 4, 8},
{5, 2, 5, 1, 5, 8, 3, 3, 7, 9, 6, 4, 4, 3, 2, 2},
{2, 6, 5, 9, 8, 6, 2, 6, 3, 7, 3, 1, 6, 8, 6, 7},
{5, 8, 5, 5, 4, 6, 2, 9, 4, 0, 8, 1, 0, 5, 8, 7},
{9, 7, 4, 2, 8, 5, 5, 5, 0, 7, 0, 6, 8, 3, 5, 3},
{4, 2, 9, 6, 8, 4, 9, 6, 4, 3, 6, 0, 7, 5, 4, 3},
{7, 8, 9, 0, 9, 7, 1, 5, 4, 8, 9, 0, 8, 0, 6, 7},
{8, 6, 9, 0, 0, 9, 5, 8, 5, 1, 5, 2, 6, 2, 5, 4},
{1, 7, 4, 8, 2, 7, 0, 4, 7, 6, 7, 5, 8, 2, 7, 6},
{3, 0, 4, 1, 6, 3, 1, 1, 1, 7, 2, 2, 4, 6, 3, 5},
{1, 8, 4, 1, 2, 3, 6, 4, 5, 4, 3, 2, 4, 5, 8, 9}
};
int B[N] = {0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3};
bool dfs1(int, int);
bool dfs2(int f, int finish, int f1, int cnt, int st, char *neglect) {
if (f1 == cnt) {
for (int i = 0; i < M; i++)
vis[i][A[f][i]]++;
if (dfs1(f + 1, finish + cnt)) return true;
for (int i = 0; i < M; i++)
vis[i][A[f][i]]--;
return false;
}
for (int i = st; i < M; i++) {
if (neglect[i]) continue;
tmp[i] = A[f][i];
if (dfs2(f, finish, f1 + 1, cnt, i + 1, neglect)) return true;
tmp[i] = -1;
}
return false;
}
bool dfs1(int f, int finish) {
if (f == N) {
for (int i = 0; i < M; i++) {
if (tmp[i] == -1) {
for (int j = 0; j < D; j++) {
if (vis[i][j] == 0)
tmp[i] = j;
}
}
}
return true;
}
int cnt = B[f];
for (int i = 0; i < M; i++)
cnt -= (A[f][i] == tmp[i]);
if (cnt < 0)return false;
char neglect[M] = {0};
for (int i = 0; i < M; i++)
if (tmp[i] != -1 || vis[i][A[f][i]]) neglect[i] = 1;
if (dfs2(f, finish, 0, cnt, 0, neglect)) return true;
return false;
}
int main() {
memset(tmp,-1,sizeof(tmp));
dfs1(0, 0);
string ans;
for (int i = 0; i < M; i++)
ans += char('0' + tmp[i]);
cout << ans << endl;
return 0;
}
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
Ujimatsu Chiya 微信 微信
Ujimatsu Chiya 支付宝 支付宝