#include <bits/stdc++.h>
using namespace std;
struct block
{
int x1, y1, x2, y2, c;
}a[16];
int N;
int color[21] = {0};
int m;
int ans=16;
bool f[16][16] = { false };
int b[16] = {0};//砖块被涂的次数
bool cmp(block a,block b)
{
if (a.x1 != b.x1)
return a.x1 < b.x1;
else
return a.y1 < b.y1;
}
bool ok(int o)
{
for (int i = 1; i <= N; i++)
if (f[o][i] &&!b[i])//如果上紧挨着o砖块的i砖块没有涂色,就o砖块不能涂
return false;
return true;
}
void dfs(int o,int pq,int xx)//o抬手次数 pq涂过颜色的砖的数量 xx上次涂的颜色
{
if (o >= ans)
return;//当前涂色次数大于等于当前答案,直接退出
if (pq == N)//涂完了砖
{
ans = o;
return;
}
for (int i = 1; i <= m; i++)//枚举用的颜色
{
int qq = 0;//用i颜色涂过的砖数
if (color[i] && i != xx)//如果有i这种颜色并且这不是上次涂的颜色,就要加抬手次数了
{
for (int j = 1; j <= N; j++)//枚举砖块
{
if (!b[j] && ok(j)&&a[j].c==i)//如果j砖块没涂过并且能涂
{
b[j] = 1;
qq++;
}
else if (b[j] && a[j].c == i)
{//递归的话同一个砖块可能被涂多次,但是也要算上去,不然如果没算上去的话,有可能在回溯的时候就会缺失明明可以涂却没有图上的情况
b[j]++;
}
}
if (qq > 0)
dfs(o + 1, pq + qq, i);
for (int j = N; j >= 1; j--)
{
if (b[j] == 1 && ok(j) && a[j].c == i)
{
b[j] = 0;
qq--;
}
else if (b[j] > 1 && a[j].c == i)
{
b[j]--;
}
}
}
}
}
int main()
{
scanf("%d", &N);
for (int i = 1; i <= N; i++)
{
scanf("%d%d%d%d%d", &a[i].x1, &a[i].y1, &a[i].x2, &a[i].y2, &a[i].c);
a[i].x1++; a[i].y1++;
color[a[i].c]++;
}
for (int i = 1; i <= 20; i++)
if (color[i])
m = i;//记录最大的颜色编号
sort(a + 1, a + N + 1,cmp);//以纵为先,横为后排序
for (int i = 2; i <= N; i++)
for (int j = i - 1; j >= 1; j--)//判断第i个方块是不是紧挨着上方的第j个方块
if (a[i].x1==a[j].x2+1&&(a[i].y1>=a[j].y1&&a[i].y1<=a[j].y2
||a[i].y2>=a[j].y1&&a[i].y2<=a[j].y2))
//要么左边点在中间,要么右边点在中间
f[i][j] = true;
dfs(0, 0, 0);
printf("%d", ans);
return 0;
}