Problem:
Score : 800 points

Problem Statement

Mr. Takahashi has in his room an art object with H rows and W columns, made up of H \times W blocks.
Each block has a color represented by a lowercase English letter (a-z).
The color of the block at the i-th row and j-th column is c_{i,j}.

Mr. Takahashi would like to dismantle the object, finding it a bit kitschy for his tastes.
The dismantling is processed by repeating the following operation:

Choose one of the W columns and push down that column one row.
The block at the bottom of that column disappears.

Each time the operation is performed, a cost is incurred.
Since blocks of the same color have a property to draw each other together, the cost of the operation is the number of the pairs of blocks (p, q) such that:

The block p is in the selected column.

The two blocks p and q are horizontally adjacent (before pushing down the column).

The two blocks p and q have the same color.

Mr. Takahashi dismantles the object by repeating the operation H \times W times to get rid of all the blocks.
Compute the minimum total cost to dismantle the object.

Constraints

1 ≤ H ≤ 300

2 ≤ W ≤ 300

All characters c_{i,j} are lowercase English letters (a-z).

Partial Score

In test cases worth 300 points, W = 3.

Input

The input is given from Standard Input in the following format:

H W
c_{1,1}c_{1,2}..c_{1,W}
c_{2,1}c_{2,2}..c_{2,W}
:
c_{H,1}c_{H,2}..c_{H,W}

Output

Print the minimum total cost to dismantle the object.

Sample Input 1

2 3
rrr
brg

Sample Output 1

2

For example, the total cost of 2 can be achieved by performing the operation as follows and this is the minimum value.

Sample Input 2

6 3
xya
xya
ayz
ayz
xaz
xaz

Sample Output 2

0

The total cost of 0 can be achieved by first pushing down all blocks of the middle column, then all of the left column, and all of the right column.

Sample Input 3

4 2
ay
xa
xy
ay

Sample Output 3

0

The total cost of 0 can be achieved by the following operations:

pushing down the right column one row;

pushing down the left column one row;

pushing down all of the right column;

and pushing down all of the left column.

Sample Input 4

5 5
aaaaa
abbba
ababa
abbba
aaaaa

Sample Output 4

24

Sample Input 5

7 10
xxxxxxxxxx
ccccxxffff
cxxcxxfxxx
cxxxxxffff
cxxcxxfxxx
ccccxxfxxx
xxxxxxxxxx

Sample Output 5

130

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <vector>
#include <iostream>
#include <utility>
#include <algorithm>
#include <string>
#include <deque>
#include <queue>
#include <functional>
#include <cmath>
#include <iomanip>
#include <map>
#include <numeric>
#include <list>
#include <assert.h>
#include <math.h>
#include <valarray>
#include <stdio.h>
#include <algorithm>
#include <set>
#include <complex>

using namespace std;
typedef long long int LL;
typedef pair<long long int, long long int> pii;
typedef pair<double, double> pdd;

#define SORT(c) sort((c).begin(),(c).end())
#define BACKSORT(c) sort((c).begin(),(c).end(),std::greater<LL>())
#define FOR(i,a,b) for(LL i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)


int main()
{
	int H, W;
	cin >> H >> W;
	vector<vector<int>>c(H+1, vector<int>(W+2));
	REP(i, H) {
		string s;
		cin >> s;
		REP(j, W) {
			c[i][j+1] = (int)s[j]-'a';
		}
		c[i][0] = -1;
		c[i][W+1] = -1;
	}
	int costs = 0;
	REP(i, H) {
		FOR(j, 1, W + 1) {
			if (c[i][j] == c[i][j + 1]) {
				costs++;
			}
		}
	}
	vector<int> nokori(W + 2,H);
	vector<int> cost(W + 2,0);
	vector<int> future(W + 2,0);
	cost[0] = 2000000000;
	int index = 0;
	FOR(j, 1, W + 1) {

		if (nokori[j] == 0) {
			cost[j] = 2000000000;
		}
		else {

			REP(i, H - 1) {
				if (j + 1 <= W) {

					if (c[i][j] == c[i + 1][j + 1]&&c[i][j]!=-1) {
						cost[j]++;
					}
				}
				if (j - 1 >= 0) {
					if (c[i][j] == c[i + 1][j - 1] && c[i][j] != -1) {
						cost[j]++;
					}
				}
			}
			REP(i, H - 1) {
				if (j + 1 <= W) {
					if (c[H - 1][j] == c[i][j + 1] && c[H-1][j] != -1) {
						future[j]++;
					}
				}
				if (j - 1 >= 0) {
					if (c[H - 1][j] == c[i][j - 1] && c[H - 1][j] != -1) {
						future[j]++;
					}
				}
			}
		}
		if (cost[j] - future[j] < cost[index] - future[index]) {
			index = j;
		}
		else 
			if (cost[j] - future[j] == cost[index] - future[index]) {
				if (cost[j] < cost[index]) {
					index = j;
				}
		}
	}

	REP(uwaaaaaaaaa, H*W) {
		costs += cost[index];
		for (int j = H - 1; j >= 1; --j) {
			c[j][index] = c[j - 1][index];
		}
		c[0][index] = -1;
		nokori[index]--;

		int ind = index;
		FOR(j, -1+ind, ind + 2) {

			if (nokori[j] == 0) {
				cost[j] = 2000000000;
			}
			else {
				cost[j] = 0;
				future[j] = 0;
				REP(i, H - 1) {
					if (j + 1 <= W) {

						if (c[i][j] == c[i + 1][j + 1] && c[i][j] != -1) {
							cost[j]++;
						}
					}
					if (j - 1 >= 0) {
						if (c[i][j] == c[i + 1][j - 1] && c[i][j] != -1) {
							cost[j]++;
						}
					}
				}
				REP(i, H - 1) {
					if (j + 1 <= W) {
						if (c[H - 1][j] == c[i][j + 1] && c[H - 1][j] != -1) {
							future[j]++;
						}
					}
					if (j - 1 >= 0) {
						if (c[H - 1][j] == c[i][j - 1] && c[H - 1][j] != -1) {
							future[j]++;
						}
					}
				}
			}
		}

		cost[0] = 2000000000;
		index = 0;
		FOR(j, 1, W + 1) {
			if (cost[j] - future[j] < cost[index] - future[index]) {
				index = j;
			}
			else
				if (cost[j] - future[j] == cost[index] - future[index]) {
					if (cost[j] < cost[index]) {
						index = j;
					}
				}
		}
		index=index;
	}
	cout << costs << endl;
}