题面来自于某nb网友
简单题意
给定
3
∗
3
3*3
3∗3的数独,给你固定的区域划分,除了满足基础数独还有满足区域划分的答案。
基础数独就是同行同列都是不同的数,这里的区域就是将
3
∗
3
3*3
3∗3的数独划分成三个区域,要求这三个区域内的数也不同。
简单思路
每个位置可以为123三种情况,3的9次方是19683,也就是最多有不到2万种情况,可以枚举所有情况进行判断,考虑到只有十组数据,可以直接随机,减少代码量。
ps剪支小技巧:当有两种情况满足时直接剪枝返回,加快速度。
输入输出描述和样例
t组测试,每组测试包含两部分,第一部分是
3
∗
3
3*3
3∗3的数独矩阵只包含
1
1
1
2
2
2
3
3
3和
∗
*
∗,第二部分是三行,每行六个数表示一个区域的三个位置。
输出的话如果答案有多种输出
M
u
l
t
i
p
l
e
Multiple
Multiple,如果只有一种答案输出
U
n
i
q
u
e
Unique
Unique之后把答案填充的数独输出,如果不存在答案输出
N
o
No
No。
输入
4
*2*
1*2
***
0 0 0 1 1 0
0 2 1 1 1 2
2 0 2 1 2 2
**3
***
***
0 0 1 0 1 1
0 1 0 2 1 2
2 0 2 1 2 2
**3
1**
**2
0 0 1 0 1 1
0 1 0 2 1 2
2 0 2 1 2 2
3*3
1**
**2
0 0 1 0 1 1
0 1 0 2 1 2
2 0 2 1 2 2
输出
Unique
321
132
213
Multiple
No
No
参考代码(我认为比较短)
#include <iostream>
#include <set>
using namespace std;
const int N = 10;
char s[N][N];
char s2[N][N];
int mp[N][N];
void cp()
{
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
s2[i][j] = s[i][j];
}
int rd(int l, int r)
{
return rand() % (r - l + 1) + l;
}
bool check()
{
for (int i = 1; i <= 3; i++)
for (int j1 = 1; j1 <= 3; j1++)
for (int j2 = j1 + 1; j2 <= 3; j2++)
if (s2[i][j1] == s2[i][j2])
return 0;
for (int i = 1; i <= 3; i++)
for (int j1 = 1; j1 <= 3; j1++)
for (int j2 = j1 + 1; j2 <= 3; j2++)
if (s2[j1][i] == s2[j2][i])
return 0;
for (int i = 1; i <= 3; i++)
{
if (s2[mp[i][1]][mp[i][2]] == s2[mp[i][3]][mp[i][4]])
return 0;
if (s2[mp[i][1]][mp[i][2]] == s2[mp[i][5]][mp[i][6]])
return 0;
if (s2[mp[i][3]][mp[i][4]] == s2[mp[i][5]][mp[i][6]])
return 0;
}
return 1;
}
void solve()
{
for (int i = 1; i <= 3; i++)
cin >> s[i] + 1;
int num = 0;
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
num += s[i][j] == '*';
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 6; j++)
{
cin >> mp[i][j];
mp[i][j]++;
}
int cnt = 2e6;
set<string> st;
while (cnt--)
{
cp();
string res = "";
for (int i = 1; i <= num; i++)
res += '0' + rd(1, 3);
int idx = 0;
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
if (s2[i][j] == '*')
s2[i][j] = res[idx++];
if (check())
st.insert(res);
if (st.size() >= 2)
{
puts("Multiple");
return;
}
}
if (st.size() == 0)
{
puts("No");
return;
}
puts("Unique");
string res = *st.begin();
cp();
int idx = 0;
for (int i = 1; i <= 3; i++)
{
for (int j = 1; j <= 3; j++)
cout << (s2[i][j] == '*' ? res[idx++] : s2[i][j]);
cout << endl;
}
}
int main()
{
srand(time(NULL));
int t;
cin >> t;
while (t--)
solve();
return 0;
}
结束语
网易互娱雷火历来笔试题都是偏模拟,代码量会比较大,比如八数码,文本编辑器这种模拟题都会有,只能说是太卷了,愿天堂没有内卷。!!!!!