问题描述
格式输入
输入的第一行包含两个整数 n, m,用一个空格分隔,表示棋盘大小。接下来 n 行,每行包含 m 个字符,表示棋盘布局。字符可能是数字 0 ∼ 9,这表示网格上的数字;字符还有可能是下划线(ASCII 码为 95 ),表示一个不带有数字的普通网格。
格式输出
输出 n 行,每行包含 m 个字符,表示答案。如果网格填充白色则用字符 0表示,如果网格填充黑色则用字符 1 表示。
样例输入
6 8
1__5_1
1_4__42_
3__6__5_
56
_688___4
___6
【样例输出
样例输出
00011000
00111100
01000010
11111111
01011110
01111110
评测用例规模与约定
对于 50% 的评测用例,1 ≤ n, m ≤ 5 ;
对于所有评测用例,1 ≤ n, m ≤ 10 。
解析
分行,搜索,剪枝,由于题目保证有唯一解,所以搜索的复杂度是正确的。添加链接描述
参考程序
dfs
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<string> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
vector<vector<int>> ans(n, vector<int>(m, -1));
auto get = [&](int i, int j) {
array<int, 3> res = {0, 0, 0};
for (int mx = -1; mx <= 1; mx++) {
for (int my = -1; my <= 1; my++) {
int I = i + mx;
int J = j + my;
if (I < 0 || I >= n) {
continue;
}
if (J < 0 || J >= m) {
continue;
}
if (ans[I][J] == 1) {
res[1]++;
} else if (ans[I][J] == 0) {
res[0]++;
} else {
res[2]++;
}
}
}
return res;
};
auto check = [&](int i) {
for (int j = 0; j < m; j++) {
if (a[i][j] >= '0' && a[i][j] <= '9') {
int num = a[i][j] - '0';
auto x = get(i, j);
int zero = x[0];
int one = x[1];
int no = x[2];
if (one > num) {
return false;
}
if (no + one < num) {
return false;
}
}
}
return true;
};
function<void(int, int)> dfs = [&](int i, int j) {
if (i == n) {
for (int I = 0; I < n; I++) {
for (int J = 0; J < m; J++) {
cout << ans[I][J];
}
cout << '\n';
}
return;
}
if (j == m) {
if (i > 0) {
if (check(i - 1) && check(i)) {
dfs(i + 1, 0);
}
} else if (check(i)) {
dfs(i + 1, 0);
}
return;
}
ans[i][j] = 1;
dfs(i, j + 1);
ans[i][j] = 0;
dfs(i, j + 1);
ans[i][j] = -1;
};
dfs(0, 0);
return 0;
}
状压DP
#include <stdio.h>
#include <bitset>
char grid[11][12], *mp, mp8[1 << 22], mp5[1 << 22], last[11];
std::bitset<1 << 22> dp[101]{1};
bool ans[11][11];
int n, m;
inline int get(int n, int i) { return (n >> i) & 1; }
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%s", grid[i] + 1);
for (int j = 1; j <= m; ++j)
if (grid[i][j] != '_') grid[i][j] -= '0';
else grid[i][j] = 0;
}
int pm2 = 1 << (2 * m + 2), mod = pm2 - 1;
for (int i = 0; i < pm2; ++i) {
mp5[i] = get(i, m - 1) + get(i, 2 * m - 1);
if (m > 1) mp5[i] += get(i, 0) + get(i, m) + get(i, 2 * m);
mp8[i] = mp5[i] + get(i, 1) + get(i, m + 1) + get(i, 2 * m + 1);
}
int now = 0, old;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
old = now, ++now;
mp = j != 2 ? mp8 : mp5;
for (int s = 0; s < pm2; ++s) dp[now][s] = 0;
if (grid[i - 1][j - 1]) {
char temp = grid[i - 1][j - 1], temp1 = temp - 1;
for (int s = 0; s < pm2; ++s)
if (dp[old][s]) {
if (temp == mp[s]) dp[now][(s << 1) & mod] = 1;
else if (temp1 == mp[s]) dp[now][((s << 1) | 1) & mod] = 1;
}
} else {
for (int s = 0; s < pm2; ++s)
if (dp[old][s]) dp[now][(s << 1) & mod] = dp[now][((s << 1) | 1) & mod] = 1;
}
}
for (int s = 0; s < pm2; ++s)
if (dp[now][s] && grid[i - 1][m]) dp[now][s] = grid[i - 1][m] == mp5[s >> 1] + (s & 1);
}
int s = 0;
for (; s < pm2;++s)
if (dp[now][s]) {
bool flag = 1;
for (int i = 1; i <= m; ++i) last[i] = get(s, m - i) + get(s, 2 * m - i);
for (int i = 1; i <= m; ++i)
if (grid[n][i] && last[i - 1] + last[i] + last[i + 1] != grid[n][i]) {
flag = 0;
break;
}
if (flag) break;
}
for (int i = n; i; --i)
for (int j = m; j; --j) {
mp = j != 2 ? mp8 : mp5;
ans[i][j] = s & 1;
--now, s = s >> 1;
if ((grid[i - 1][j - 1] && mp[s] + ans[i][j] != grid[i - 1][j - 1]) || !dp[now][s]) s |= pm2 >> 1;
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) putchar('0' ^ ans[i][j]);
putchar('\n');
}
}
#include <iostream>
using namespace std;
int f[12][12];//下标从1开始
char d[12][12];
int n,m;
//检查填0/1时是否符合条件,当填完[x,y]时,[x-1,y-1]已经不受影响,若时最后一列,则[x-1,y]也不受影响
bool check(int x,int y){
if(d[x][y]=='_') return true;
int cnt=0;
for(int i=-1;i<=1;i++){
for(int j=-1;j<=1;j++){
cnt+=f[x+i][y+j];
}
}
if(cnt==d[x][y]-'0')
return true;
return false;
}
//深搜试探,从左往右,从上往下
void dfs(int x,int y){
if(x==n+1){//全部摆放好了,检查是否符合最后一行
for(int y=1;y<=m;y++){
if(!check(n,y))
return;
}
//找到答案,直接输出,结束
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout<<f[i][j];
}
cout<<endl;
}
return;
}
if(y==m){//到了最后一列,准备换行
f[x][y]=0;
if(x==1 || (y==1 && check(x-1,y)) || (check(x-1,y-1) && check(x-1,y))){
dfs(x+1,1);//换行
}
f[x][y]=1;//0不可行,回溯,试1
if(x==1 || (y==1 && check(x-1,y)) || (check(x-1,y-1) && check(x-1,y))){
dfs(x+1,1);//换行
}
}
else{//没到换行,遍历下一列
f[x][y]=0;
if(x==1 || y==1 ||(check(x-1,y-1)))
dfs(x,y+1);
f[x][y]=1;
if(x==1 || y==1 || check(x-1,y-1))
dfs(x,y+1);
}
}
int main()
{
// 请在此输入您的代码
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>d[i][j];
}
}
dfs(1,1);
return 0;
}
以个人刷题整理为目的,如若侵权,请联系删除~