时间限制 内存限制
1000 ms 65536 KB

# 题目描述

Moca 最近发现了一种叫做数独的益智游戏。

经典的数独规则是这样的:

  • 将一个 9×99 \times 9 的方格分为 993×33 \times 3 的小方格,每个 3×33 \times 3 方格称为一个宫

  • 开始时一些方格中的数字是给定的,玩家需要根据推理,填写剩余方格中的数字,直到所有方格中都被填上了数字

  • 最后 在每一行、每一列、每一宫中,数字 1 - 9 都出现且只出现一次,则填写正确

Moca 喜欢做数独,但她不喜欢检查自己做的数独是否正确,尽管这很简单。所以,她希望你能帮她写一个程序,对于一个给定的初始状态,检查她做的数独是否正确。

# 输入

第一行一个正整数 tt ,表示 Moca 做了多少数独,1t51 \le t \le 5

接下来 tt 组输入,每组输入之前有一个空行。每组输入 1919 行:前九行每行九个数字,为初始的数独局面,00 代表待填写的数字,其余数字代表初始给定的数字,保证初始局面中所有数字一定是 0099 中的一个;接下来一行空行;后九行每行九个数字,表示对应做出来的数独,保证做出来的数独中的数字一定是 1199 中的一个。

# 输出

输出 tt 行,如果第 ii 组做出来的数独对于第 ii 组初始局面数独填写正确,那么对应输出行输出 Moca finish this sudoku perfectly! ;否则(包括做出来的数独虽然正确,但是不符合给定的初始局面的情况)输出 Moca is so careless!

# 输入样例

3
0 2 0 4 0 0 0 0 0
4 5 0 7 0 0 0 0 3
0 8 9 0 3 0 0 0 6
2 0 0 0 0 0 8 0 0
0 9 0 0 0 0 0 6 5
3 0 5 8 7 0 2 0 0
5 0 0 0 0 0 9 7 8
6 0 0 9 0 0 0 0 1
0 7 0 5 1 0 0 4 0
1 2 3 4 5 6 7 8 9
4 5 6 7 9 8 1 2 3
7 8 9 1 3 2 4 5 6
2 1 4 3 6 5 8 9 7
8 9 7 2 4 1 3 6 5
3 6 5 8 7 9 2 1 4
5 3 1 6 2 4 9 7 8
6 4 2 9 8 7 5 3 1
9 7 8 5 1 3 6 4 2
0 2 0 4 0 0 0 0 0
4 5 0 7 0 0 0 0 3
0 8 9 0 3 0 0 0 6
2 0 0 0 0 0 8 0 0
0 9 0 0 0 0 0 6 5
3 0 5 8 7 0 2 0 0
5 0 0 0 0 0 9 7 8
6 0 0 9 0 0 0 0 1
0 7 0 5 1 0 0 4 0
1 2 3 4 5 6 7 8 9
4 5 6 7 9 8 1 2 3
7 8 9 1 3 2 4 5 6
2 1 4 3 6 5 8 9 7
8 9 7 2 4 1 3 6 5
3 6 5 8 7 9 2 1 4
5 3 1 6 2 4 9 7 8
6 4 2 9 8 7 5 3 1
9 7 8 5 1 3 6 4 1
0 2 0 4 0 0 0 0 0
4 5 0 7 0 0 0 0 3
0 8 9 0 3 0 0 0 6
2 0 0 0 0 0 8 0 0
0 9 0 0 0 0 0 6 5
3 0 5 8 7 0 2 0 0
5 0 0 0 0 0 9 7 8
6 0 0 9 0 0 0 0 1
0 7 0 5 1 0 0 4 0
1 2 3 6 5 4 7 8 9
4 5 6 9 8 7 1 2 3
7 8 9 3 2 1 4 5 6
8 9 7 4 1 2 3 6 5
3 6 5 7 9 8 2 1 4
2 1 4 5 6 3 8 9 7
5 3 1 2 4 6 9 7 8
6 4 2 8 7 9 5 3 1
9 7 8 1 3 5 6 4 2

# 输出样例

Moca finish this sudoku perfectly!
Moca is so careless!
Moca is so careless!

# 样例解释

对于第 11 组输入,补全后的数独正确,且符合初始局面;对于第 22 组输入,补全后的数独不正确,在九行和九列中都出现了两次 11;对于第 33 组输入,虽然补全后的数独正确,但并不符合初始局面(如第一行第四列初始局面给定的数字是 44 ,但是 Moca 补全的数独中对应位置的数字却是 66),所以也是错的。

# 题解:模拟

我们开两个二维数组存下初始和结束局面,随后按题意模拟即可。

参考代码:

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
int ini[10][10], ans[10][10], cnt[10];
bool CheckNumber()
{
    bool flag = true;
    for (int i = 1; i <= 9; ++ i)
        if (cnt[i] != 1)
            flag = false;
    
    return flag;
}
bool Check()
{
    bool flag = true;
    for (int i = 1; i <= 9; ++ i)
        for (int j = 1; j <= 9; ++ j)
            if (ini[i][j] && ini[i][j] != ans[i][j])
                flag = false;
    
    for (int i = 1; i <= 9; ++ i)
    {
        memset(cnt, 0, sizeof(cnt));
        for (int j = 1; j <= 9; ++ j)
            ++ cnt[ans[i][j]];
        
        if (!CheckNumber())
            flag = false;
        
        memset(cnt, 0, sizeof(cnt));
        for (int j = 1; j <= 9; ++ j)
            ++ cnt[ans[j][i]];
        
        if (!CheckNumber())
            flag = false;
    }
    for (int i = 1; i <= 9; i += 3)
        for (int j = 1; j <= 9; j += 3)
        {
            memset(cnt, 0, sizeof(cnt));
            for (int u = i; u <= i + 2; ++ u)
                for (int v = j; v <= j + 2; ++ v)
                    ++ cnt[ans[u][v]];
            
            if (!CheckNumber())
                flag = false;
        }
    
    return flag;
}
int main()
{
    // freopen("E.in", "r", stdin);
    // freopen("E.out", "w", stdout);
    int T;
    scanf("%d", &T);
    while (T -- )
    {
        for (int i = 1; i <= 9; ++ i)
            for (int j = 1; j <= 9; ++ j)
                scanf("%d", &ini[i][j]);
        
        for (int i = 1; i <= 9; ++ i)
            for (int j = 1; j <= 9; ++ j)
                scanf("%d", &ans[i][j]);
        
        if (Check())
            puts("Moca finish this sudoku perfectly!");
        else
            puts("Moca is so careless!");
    }
    return 0;
}