Problem:
連鎖

問題

次のようなゲームがある．

あるキャラクターが縦 1 列に N 個並んでいる．これらのキャラクターの色は赤，青，黄のいずれかであり，初期状態で同じ色のキャラクターが4つ以上連続して並んでいることはない．プレーヤーは，ある位置のキャラクターを選び他の色に変更することができる．この操作により同じ色のキャラクターが4つ以上連続して並ぶとそれらのキャラクターは消滅する．キャラクターが消滅することにより新たに同じ色のキャラクターが4つ以上連続して並ぶとそれらのキャラクターも消滅し，同じ色のキャラクターが4つ以上連続して並んでいる箇所がなくなるまでこの連鎖は続く．このゲームの目的は，消滅しないで残っているキャラクター数をなるべく少なくすることである．

例えば，下図の左端の状態で，上から6番目のキャラクターの色を黄色から青に変更すると，青のキャラクターが5つ連続するので消滅し，最終的に3つのキャラクターが消滅せずに残る．

初期状態における N 個のキャラクターの色の並びが与えられたとき， 1箇所だけキャラクターの色を変更した場合の，消滅しないで残っているキャラクター数の最小値 M を求めるプログラムを作成せよ．

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．

1行目はキャラクター数 N (1 ≤ N ≤ 10000) だけからなる．続く N 行には 1, 2, 3 のいずれか1つの整数が書かれており， i + 1 行目 (1 ≤ i ≤ N) は初期状態における上から i 番目のキャラクターの色を表す（1 は赤を，2 は青を，3は黄を表す）．

N が 0 のとき入力の終了を示す．データセットの数は 5 を超えない．

出力

データセットごとに, 消滅しないで残っているキャラクター数の最小値 M を１行に出力せよ．

入出力例

入力例

12
3
2
1
1
2
3
2
2
2
1
1
3
12
3
2
1
1
2
3
2
1
3
2
1
3
0

出力例

3
12

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in JAVA (judge verdict: Wrong Answer)

import java.util.*;
import java.io.*;
import static java.lang.Math.*;

class Pair {

    final int color;
    final int count;

    Pair( final int color, final int count ) {
	this.color = color;
	this.count = count;
    }

    public String toString() {
	return String.format( "(%d, %d)", color, count );
    }    
}

class Main {

    public static void main( final String[] args ) {

	final Scanner stdin = new Scanner( System.in );
	final ArrayList<Pair> lst = new ArrayList<Pair>();

	final int n = stdin.nextInt();
	
	int color = stdin.nextInt();
	int count = 1;
	for ( int i = 0; i < n - 1; i++ ) {
	    final int pcolor = stdin.nextInt();
	    if ( color == pcolor ) {
		count++;
	    } else {
		lst.add( new Pair( color, count ) );
		color = pcolor;
		count = 1;
	    }
	}
	lst.add( new Pair( color, count ) );

	//System.err.println( lst );

	int minSize = n;
	for ( int i = 1; i < lst.size() - 1; i++ ) {
	    if ( lst.get( i ).count == 1 && lst.get( i - 1 ).color == lst.get( i + 1 ).color ) {
		final int reduceNum = simulate( lst, i );
		if ( minSize > n - reduceNum ) {
		    minSize = n - reduceNum;
		}
	    }
	}
	System.out.println( minSize );
    }

    static int simulate( final ArrayList<Pair> lst, final int index ) {
	
	int number = 0;
	final int initNum = lst.get( index - 1 ).count + lst.get( index ).count + lst.get( index + 1 ).count;
	//System.err.printf( "%d: %s, %s, %s\n", index, lst.get( index - 1 ), lst.get( index ), lst.get( index + 1 ) );
	if ( initNum >= 4 ) {
	    number = initNum;
	} else {
	    return number;
	}
	int dist = 2;
	while ( 0 <= index - dist && index + dist < lst.size() &&
		lst.get( index - dist ).color == lst.get( index + dist ).color ) {

	    final int pNumber = lst.get( index - dist ).count + lst.get( index + dist ).count;
	    if ( pNumber >= 4 ) {
		number += pNumber;
		dist++;
	    } else {
		return number;
	    }
	}
	return number;		
    }    
}