Problem: Problem Statement

Mr. Takatsuki, who is planning to participate in the Aizu training camp, has a poor house and always tries to save as much paper as possible. She decided to play a ghost leg with other participants to decide the team for the Aizu training camp.

How to make Amidakuji for this training camp is as follows. First, write N vertical bars in parallel on the paper. Then, write the M horizontal bars in order from the top so that they are perpendicular to the vertical bars and the heights of the horizontal bars are all different. For example, the Amida of Sample Input 1 is as shown in Fig. 1.

Here, Mr. Takatsuki, a little dissatisfied expression. It's a waste of paper to write a ghost leg so vertically. You should be able to compress the height more. So, I want her to solve the problem of height compression of Amidakuji shown below.

First, the height of the Amidakuji is the value obtained by counting the horizontal bars that exist at the same height together as the height 1 and counting this to the bottom horizontal bar. Here, it is assumed that each horizontal bar can be freely moved up and down in order to perform height compression. However, it is not permissible to remove or add horizontal bars. The Amidakuji after height compression must meet the following conditions.

* The end points of the horizontal bar do not touch the end points of other horizontal bars.
* The result of tracing the Amidakuji after compression and the result of tracing the Amidakuji before compression match.



FIG. 2 is a compressed version of FIG. The "horizontal bar connecting vertical bars 1 and 2" moves to the top and becomes the same height as the "horizontal bar connecting vertical bars 4 and 5", and these two are height 1. After that, the "horizontal bar connecting the vertical bars 3 and 4" and the "horizontal bar connecting the vertical bars 2 and 3" have different heights, and the total height is 3.

<image>

Compress the height of the given Amidakuji and output the compressed height.

Constraints

* 2 <= N <= 8
* 1 <= M <= 8
* 1 <= ai <= N --1

Input

Each data set is input in the following format.


N M
a1
a2
...
aM


All inputs are integers. N indicates the number of vertical bars and M indicates the number of horizontal bars. Then, the information of the horizontal bar is input over M lines. ai indicates that the i-th horizontal bar connects the vertical bar ai and the vertical bar to the right of it. The i-th horizontal bar exists above the i + 1-th horizontal bar.

Output

Outputs the height of the compressed Amidakuji in one line.

Examples

Input

5 4
4
3
1
2


Output

3


Input

4 3
1
2
3


Output

3

Solution (in CPP):

Solution:
#include <stdio.h>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


struct Info{
	int count[8],dealt;
	vector<int> V;
};


int main(){

	int W,M;
	scanf("%d %d",&W,&M);

	bool check[M+1][W+1],work[M+1][W+1];
	int count[W+1];

	for(int row = 0; row <= M; row++){
		for(int col = 0; col <= W; col++)check[row][col] = false;
	}

	for(int num = 1; num <= W-1; num++)count[num] = 0;

	int tmp,height,ans = 0;
	for(int loop = 0; loop < M; loop++){
		scanf("%d",&tmp);
		count[tmp]++;

		for(height = M; height >= 1; height--){
			if(check[height][tmp-1] == true || check[height][tmp+1] == true || check[height][tmp] == true)break;
		}
		height++;
		check[height][tmp] = true;
		ans = max(ans,height);
	}

	int ans_table[W+1];
	for(int col = 1; col <= W; col++)ans_table[col] = col;

	for(int row = 1; row <= M; row++){
		for(int col = 1; col <= W-1; col++){
			if(check[row][col])swap(ans_table[col],ans_table[col+1]);
		}
	}

	queue<Info> Q;
	Info first;
	first.dealt = 0;
	for(int num = 1; num <= W-1; num++)first.count[num] = count[num];
	Q.push(first);

	int work_table[W+1],tmp_max_height;
	bool FLG;

	while(!Q.empty()){

		if(Q.front().dealt == M){

			for(int row = 1; row <= M; row++){
				for(int col = 0; col <= W; col++)work[row][col] = false;
			}

			tmp_max_height = 0;

			for(int i = 0; i < Q.front().V.size(); i++){
				tmp = Q.front().V[i];

				for(height = M; height >= 1; height--){
					if(work[height][tmp-1] == true || work[height][tmp+1] == true || work[height][tmp] == true)break;
				}
				height++;
				work[height][tmp] = true;
				tmp_max_height = max(tmp_max_height,height);
			}

			for(int col = 1; col <= W; col++)work_table[col] = col;

			for(int row = 1; row <= M; row++){
				for(int col = 1; col <= W-1; col++){
					if(work[row][col])swap(work_table[col],work_table[col+1]);
				}
			}

			FLG = true;
			for(int col = 1; col <= W; col++){
				if(ans_table[col] != work_table[col]){
					FLG = false;
					break;
				}
			}
			if(FLG){
				ans = min(ans,tmp_max_height);
			}
			Q.pop();
		}else{

			for(int num = 1; num <= W-1; num++){
				if(Q.front().count[num] == 0)continue;

				Info next_info;
				for(int k = 1; k <= W-1; k++)next_info.count[k] = Q.front().count[k];
				for(int k = 0; k < Q.front().V.size(); k++)next_info.V.push_back(Q.front().V[k]);
				next_info.V.push_back(num);
				next_info.count[num]--;
				next_info.dealt = Q.front().dealt+1;
				Q.push(next_info);
			}
			Q.pop();
		}
	}

	printf("%d\n",ans);

	return 0;
}