UVa 1103 Ancient Messages (DFS)

思路:对于每个黑像素的联通块,求出包含的白色区域有多少,根据包含白色区域的数目判断对应哪一种象形文字。

先用一遍DFS求出有多少个黑色联通块,并给每个联通块一个标号,该联通块里的每一个黑色节点都被标记上这个标号。

然后对白色的方格进行一遍DFS,目的是求出该白色联通块属于哪一个黑色联通块。求解的方法是:在白色DFS的过程中,如果遇到了一个黑色方格,那么就意味这这个白色联通块与这个黑色联通块相接,那么用一个set<int>记录一下。如果在白色DFS过程中遇到了边界,那么这个联通块是不要的,因为这必然是背景。如果该白色联通块不是背景并且只遇到了一个黑色联通块,那么对应的黑色联通块所包含的白色联通块数+1。最后根据每个黑色联通块所包含的白色区域数来判断这个联通块是什么符号,然后将结果字典序输出即可。(我的代码必须要在外围加上一圈白色的方格才能AC)

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <list>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <cctype>
#include <cmath>
#include <cstring>
#include <climits>
#include <complex>
#include <set>
#include <deque>
#define DEBUG(x) cerr<<"line:"<<__LINE__<<", "<<#x" == "<<(x)<<endl;
#define REP(i,s,n) for(int i=(int)(s);i<(int)(n);i++)
#define FOR(it,s) for(__typeof(s.begin()) it=s.begin();it!=s.end();it++)
#define ALL(a) (a).begin(),(a).end()
#define RALL(x) (a).rbegin(),(a).rend()
#define RI(x) scanf("%d",&(x))
#define RII(x,y) scanf("%d%d",&(x),&(y))
#define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define DRI(x) int (x);scanf("%d",&(x))
#define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
#define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
#define MS0(a) memset((a),0,sizeof((a)))
#define MS1(a) memset((a),-1,sizeof((a)))
#define MS(a,b) memset((a),(b),sizeof((a)))
#define PB push_back
#define SZ(a) (int)(a).size()

using namespace std;

typedef long long LL;
typedef unsigned int uint;
typedef unsigned long long ULL;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pii> vii;
typedef vector<vi> vvi;

#define INF 1000000000
const double eps = 1e-10;
int dcmp(double x){
  if(fabs(x) < eps) return 0;
  else return x < 0 ? -1 : 1;
}
// ------------------
// author : onehrxn
// ------------------
const int maxn = 200 + 10;
int H, W;
struct node{
  bool c;
  int id;
};
node m[maxn][maxn];
int vis[maxn][maxn];
inline void to_bit(char tmp, int r, int c){
  int num = 0;
  if( '0' <= tmp && tmp <= '9') num = tmp - '0';
  else num = tmp - 'a' + 10;
  int tc[4];
  int cur = 3;
  for(int i = 0; i < 4; i++){
    tc[cur] = num % 2;
    cur--;
    num /= 2;
  }
  for(int i = 0; i < 4; i++){
    m[r][c*4 + i + 1].c = tc[i];
  }
}
int dr[] = {-1, 0, 0, 1};
int dc[] = {0, -1, 1, 0};
inline bool ok(int r, int c){
  if(r < 0 || r >= H + 2) return 0;
  if(c < 0 || c >= W*4 + 2) return 0;
  return 1;
}
int have[maxn];
void b_dfs(int r, int c, int id){
  m[r][c].id = id;
  vis[r][c] = 1;
  for(int i = 0; i < 4; i++) {
    int newr = r + dr[i], newc = c + dc[i];
    if(ok(newr,newc) && (m[newr][newc].c==1) && (!vis[newr][newc]))
      b_dfs(newr, newc, id);
  }
}
set<int> meet_black;
bool w_dfs(int r, int c){
  vis[r][c] = 1;
  int flag = 1;
  for(int i = 0; i < 4; i++){
    int newr = r + dr[i], newc = c + dc[i];
    if(ok(newr, newc)){
      if(vis[newr][newc] && m[newr][newc].c == 1){ // meet the black
        meet_black.insert(m[newr][newc].id);
      }
      else if(!vis[newr][newc] && m[newr][newc].c == 0){ // a new white
        w_dfs(newr, newc);
      }
    }
    else flag = 0;
  }
  return flag;
}

map<int, char> mp;
int main(void)
{
  ios::sync_with_stdio(false);
  cin.tie(0);
#ifdef LOCAL
  //freopen("input", "r", stdin);
  //freopen("output", "w", stdout);
#endif
  int kase = 1;
  mp[1] = 'A'; mp[3] = 'J'; mp[5] = 'D'; mp[4] = 'S';
  mp[0] = 'W'; mp[2] = 'K';
  while(cin >> H >> W){
    if(!H && !W) break;
    MS0(m);
    meet_black.clear();
    char tmp;
    for(int i = 1; i <= H; i++) {
      for(int j = 0; j < W; j++) {
        cin >> tmp;
        to_bit(tmp, i, j);
      }
    }
    for(int i = 0; i <= W*4 + 1; i++) m[0][i].c = 0;
    for(int i = 0; i <= H + 1; i++) m[i][0].c = 0;
    for(int i = 0; i <= H + 1; i++) m[i][W*4 + 1].c = 0;
    for(int i = 0; i <= W*4 + 1; i++) m[H+1][i].c = 0;
    
    // first get the black block and give all the black pixel an id
    MS0(vis);
    int cnt = 0;
    for(int i = 0; i <= H + 1; i++) {
      for(int j = 0; j <= 4*W + 1; j++) {
        if(!vis[i][j] && m[i][j].c == 1) {b_dfs(i,j,cnt);cnt++;}
      }
    }
    MS0(have);
    for(int i = 0; i <= H + 1; i++){
      for(int j = 0; j <= 4*W + 1; j++){
        if(!vis[i][j] && m[i][j].c == 0) {
          meet_black.clear();
          if(w_dfs(i,j)){
            if(meet_black.size() == 1){
              FOR(it, meet_black){
                have[*it]++;
              }
            }
          }
          else continue;
        }
      }
    }
    vector<char> ans;

    for(int i = 0; i < cnt; i++) {
      ans.PB(mp[have[i]]);
    }
    sort(ALL(ans));
    cout << "Case " << kase++ << ": ";
    FOR(it, ans) cout << *it;
    cout << '\n';
    //cout << res << '\n';
  }
#ifdef LOCAL
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值