状态枚举,0表示非雷,1表示雷,总共2的16次方种情况,如果出现雷在标数字的点位直接跳过,或者标数字点位周围的雷的数量不对也跳过,否则就是合法的方案,对于sta==1,对点位标记|1,sta==0,点位标记|2,那么,假设这个点最后标记结果为3,就说明这个点可能是雷也可能不是雷,则输出'.',否则就按照标记的结果输出,当然,点位是数字的话就直接输出数字。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char c[5][5];
int cnt[5][5];
int dirx[8]={1,-1,-1,1,1,-1,0,0};
int diry[8]={1,-1,1,-1,0,0,1,-1};
int d;
int range = 1<<16;
bool check(ll x)
{
    for(int i=1;i<=4;i++)
    {
        for(int j=1;j<=4;j++)
        {
            int w = (i-1)*4+(j-1);
            int sta = (x>>w)&1;
            if(sta==1&&c[i][j]>='0'&&c[i][j]<='9')return false;
            
            if(c[i][j]>='0'&&c[i][j]<='9')
            {
                int cur = c[i][j]-'0';
                int cnt = 0;
                for(int k=0;k<8;k++)
                {
                    int cx = i+dirx[k];
                    int cy = j+diry[k];
                    if(cx<1||cy<1||cx>4||cy>4)continue;
                    int w2 = (cx-1)*4+(cy-1);
                    int sta2 = (x>>w2)&1;
                    if(sta2)cnt++;
                }
                if(cnt!=cur)return false;
            }
        }
    }
    return true;
}

int main()
{
    for(int i=1;i<=4;i++)
    {
        for(int j=1;j<=4;j++)cin>>c[i][j];
    }
    for(int i=0;i<=range-1;i++)
    {
        if(check(i))
        {
            for(int a=1;a<=4;a++)
            {
                for(int b=1;b<=4;b++)
                {
                    int w = (a-1)*4+(b-1);
                    int sta = (i>>w)&1;
                    if(sta)cnt[a][b]|=1;
                    else cnt[a][b]|=2;
                }
            }
        }
    }
    for(int i=1;i<=4;i++)
    {
        for(int j=1;j<=4;j++)
        {
            if(c[i][j]>='0'&&c[i][j]<='9')cout<<c[i][j];
            else if(cnt[i][j]==3)cout<<'.';
            else if(cnt[i][j]==1)cout<<'X';
            else cout<<'O';
        }
        cout<<endl;
    }
    return 0;
}