第十四届蓝桥杯大赛软件赛省赛 C/C++ 大学 A 组 I题

问题描述

在这里插入图片描述
在这里插入图片描述


格式输入

输入的第一行包含两个整数 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;
}

以个人刷题整理为目的,如若侵权,请联系删除~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值