AOJ : 1235 - Life Line
問題概要
http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=1235
問題文中の図のように, 正三角形型のグラフが入力で与えられます. 各ノードには, 0~9 の値のいずれかが書かれています.
隣接している同じ値は全てひとまとめにして, これを一つのグループと呼びます. グループは, グループに隣接するノードに 0 がなければ, 全て 0 に変化します(問題文 Figure3b -> 3c).
この問題では, 入力 C (1 <= C <= 9) が与えられ, この数字をグラフの 0 のノードのどこかに書き込んだときの最高得点を求める問題です.
得点の計算法は次のとおりです.
- C を書き込んだとき, 0 に変化する C 以外のグループのノード数 = プラスの得点.
- C を書き込んだとき, 0 に変化する C のグループのノード数 = マイナスの得点.
例えば, Figure 4b -> 4c は, C = 2 のときで,
- C のグループ以外で消えたノード数 = +4
- C のグループで消えたノード数 = -3
となり, 4 - 3 = 1 が得点となります.
アルゴリズム
全探索で解けます.
0 のノードを順番に見ていって, C に変化させて, 得点がいくらか計算しながら最高得点を求めました.
プログラム
int n,c; int t[10][10],used[10][10]; bool zeroFlg; //あるグループに 0 が隣接したかどうか int dx[] = {-1, 0, 1, 1, 0,-1}; int dy[] = {-1,-1, 0, 1, 1, 0}; //グループのノード数を求める int dfs(int x,int y,int number){ int res = 1; used[y][x] = 1; rep(i,6){ int nx = x + dx[i]; int ny = y + dy[i]; if(ny>=0 && ny<n && nx>=0 && nx<=ny){ if(t[ny][nx]==0) zeroFlg = true; if(t[ny][nx]==number && !used[ny][nx]){ int tmp = dfs(nx,ny,number); res += tmp; } } } return res; } //現在の配列 t の内容に対して最大点数を求める int solve(void){ memset(used,0,sizeof(used)); int res = 0; rep(i,n) rep(j,i+1){ if(t[i][j]>0 && !used[i][j]){ zeroFlg = false; int tmp = dfs(j,i,t[i][j]); if(zeroFlg) continue; if(t[i][j] == c){ res -= tmp; } else{ res += tmp; } } } return res; } int main(void){ while(cin>>n>>c,c||c){ rep(i,n) rep(j,i+1) cin>>t[i][j]; int ans = -1000; //0 のノードを順番に c に変えて探索する rep(i,n) rep(j,i+1) if(t[i][j]==0){ t[i][j] = c; ans = max(ans,solve()); t[i][j] = 0; } cout<<ans<<endl; } return 0; }