题解:P12224 [蓝桥杯 2023 国 Java B] 数和游戏
sanhaoxuezha · · 题解
本题为一道简单的搜索题,思维难度并不大,但码量较大。
可以用结构体来表示格子和条目
初始化就是将每个条目的数值和每个格子的所属条目记录。
搜索就是把每个格子中可填入的数搜一遍。
接着就没什么要说的了,就是初始化和搜索,主要讲解在代码里。
#include<bits/stdc++.h>
using namespace std;
//记录格子
struct Block
{
int color; //颜色
int a,b; //如果颜色为灰,记录条目
int num; //如果颜色为白,记录填入数字
vector<int> item; //如果颜色为白,记录所有所属的条目,其实这里可以用一个pair容器来记录,但为图方便,用vector记录
};
//记录条目
struct Line
{
int lastx,lasty; //条目中最后一个格子的坐标
int remain; //条目中还未被填入的格子数量
bool vis[10]; //记录每个数字是否被用过
};
const int N=20;
Block block[N][N];
Line line[N*N]; //其实这里开50就够了
int n,m;
bool flag=0; //记录是否找到答案
int cnt=0; //line数组大小,其实line数组完全可以用vector代替,但这样会比较麻烦
//输出
void output()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(block[i][j].color==2) cout<<'_';
else cout<<block[i][j].num;
cout<<' ';
}
cout<<'\n';
}
}
//初始化
void init()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(block[i][j].color==2) //如果本格为灰色格子
{
if(block[i][j].b!=-1) //竖条目
{
line[cnt].remain=block[i][j].b;
line[cnt].lastx=i;
for(int k=j+1;k<=m;k++)
{
if(block[i][k].color==2) break;
line[cnt].lasty=k;
block[i][k].item.push_back(cnt);
}
cnt++;
}
if(block[i][j].a!=-1) //横条目
{
line[cnt].remain=block[i][j].a;
line[cnt].lasty=j;
for(int k=i+1;k<=n;k++)
{
if(block[k][j].color==2) break;
line[cnt].lastx=k;
block[k][j].item.push_back(cnt);
}
cnt++;
}
}
}
//搜索
void dfs(int k)
{
if(k==n*m) //终止条件
{
flag=1;
output();
return ;
}
int x=k/n+1,y=k%n+1; //坐标
if(block[x][y].color==2) //如果本格颜色为灰,跳过
{
dfs(k+1);
return ;
}
for(int i=1;i<=9;i++) //枚举数字
{
bool flag2=1;
for(int it:block[x][y].item)
if(line[it].vis[i] || line[it].remain<i || (x==line[it].lastx && y==line[it].lasty && line[it].remain!=i)) //是否可以填
{
flag2=0;break;
}
if(!flag2) continue; //若不可以,跳过
block[x][y].num=i; //填入
for(int it:block[x][y].item) //打标记
{
line[it].vis[i]=1;
line[it].remain-=i;
}
dfs(k+1);
if(flag) return ;
block[x][y].num=0;
for(int it:block[x][y].item) //去标记
{
line[it].vis[i]=0;
line[it].remain+=i;
}
}
}
signed main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>block[i][j].color;
if(block[i][j].color==2) cin>>block[i][j].a>>block[i][j].b;
}
init();
dfs(0);
return 0;
}