arrows blog

解いた問題などを適当に書いていきます。

AOJ 1235 - Life Line

問題概要

N段のピラミッド構造が入力として与えられ、これは下図のようなノードとエッジの関係がある。
f:id:arrows1011:20141023230646g:plain

各ノードには0〜9の数字が書かれている。このとき、入力として与えられた値Cを任意の値が0のノードに上書きしたとき、次のルールに従い、得られる得点の最大値を求めよ。

ルール

全てのノードに対して隣接する全ての同じ数字をグループ化する。そしてそのグループが値0のノードに接してなければそのグループの数のポイントを得られる。ただしそのグループがCならばその数だけポイントを失う。

制約

3 ≤ N ≤ 10
1 ≤ C ≤ 9

解法

全探索。
値が0の全てのノードに対してCに上書きし、得られる結果の最大を取る。

コード

#include <bits/stdc++.h>
  
using namespace std;
  
int N,C,cnt;
bool flg,visited[10][10];
vector<int> G[10];
int dx[6] = {-1,-1,0,0,1,1};
int dy[6] = {-1,0,-1,1,0,1};
  
bool inField(int x,int y){
  if(x > y || y >= N || x < 0 || y < 0){
    return false;
  }
  return true;
}
  
bool dfs(int x,int y,int c){
  if(G[y][x] == 0) return true;
  if(G[y][x] != c || visited[y][x]) return false;
  visited[y][x] = true; cnt++;
  bool res = false;
  for(int i = 0 ; i < 6 ; i++){
    int nx = x + dx[i];
    int ny = y + dy[i];
    if(!inField(nx,ny)) continue;
    res |= dfs(nx,ny,c);
  }
  return res;
}
 
int solve(int x,int y){
  int res = 0;
  memset(visited,false,sizeof(visited));
  for(int i = 0 ; i < N ; i++){
    for(int j = 0 ; j <= i ; j++){
      if(G[i][j] == 0) continue;
      if(visited[i][j]) continue;
       
      cnt = 0; flg = false;
      if(dfs(j,i,G[i][j])) continue;
      res += (G[i][j] != C ? cnt : -cnt);
    }
  }
  return res;
}
  
int main(){
  int in;
  while(cin >> N >> C,(N|C)){
    for(int i = 0 ; i < N ; i++){
      G[i].clear();
      for(int j = 0 ; j <= i ; j++){
        cin >> in;
        G[i].push_back(in);
      }
    }
    int res = INT_MIN;
    for(int i = 0 ; i < N ; i++){
      for(int j = 0 ; j <= i ; j++){
        if(G[i][j] == 0){
          G[i][j] = C;
          res = max(res,solve(j,i));
          G[i][j] = 0;
        }
      }
    }
    cout << res << endl;
  }
  return 0;
}