/* POJ 2836状态压缩dp
只有15个点,每个点用二进制中的一位来表示
预处理,枚举n*(n-1)/2个矩形,每个矩形的有自己的状态(覆盖的点)和面积
状态转移方程
 for(i,0,rectanglenum)             
    for(st,0,(1<<n))
        if(第i个矩形覆盖的点未全部加进集合) 
             dp[nst]=min(dp[nst],dp[st]+area[i];
其中nst为点加进集合后的新状态 
*/  
#include
< iostream >
#include
< algorithm >
#include
< cmath >
#define  REP(i,n) for(int i=0;i<n;i++)
#define  FOR(i,L,R) for(int i=L;i<=R;i++)
#define  INF 10000000
using   namespace  std;
struct  point{
    
int  x,y;
}pt[
15 ];
struct  node{
    
int  state,area;
}rec[
200 ];
int  rnum = 0 ; // 矩形的数量 
int  dp[( 1 << 15 )];
int  n;
int  main()
{
    
while (scanf( " %d " , & n) != EOF && n)
    {
        rnum
= 0 ;
        REP(i,n)
            scanf(
" %d %d " , & pt[i].x, & pt[i].y);
        REP(i,n)
        {
            FOR(j,i
+ 1 ,n - 1 )
            {
                
int  st = ( 1 << i) + ( 1 << j);
                REP(k,n)
                    
if ((pt[k].x - pt[i].x) * (pt[k].x - pt[j].x) <= 0 && (pt[k].y - pt[i].y) * (pt[k].y - pt[j].y) <= 0 )
                        st
|= ( 1 << k);
                rec[rnum].state
= st;
                
if (pt[i].x == pt[j].x)
                    rec[rnum
++ ].area = abs(pt[j].y - pt[i].y);
                
else   if (pt[i].y == pt[j].y)
                    rec[rnum
++ ].area = abs(pt[j].x - pt[i].x);
                
else  rec[rnum ++ ].area = abs(pt[j].x - pt[i].x) * abs(pt[j].y - pt[i].y);
            }
        }
        fill_n(dp,(
1 << 15 ),INF); 
        dp[
0 ] = 0 ;
        REP(i,rnum)
        {
            REP(st,(
1 << n) - 1 )
            {
                
if (dp[st] == INF)
                    
continue ;
                
if ((st | (rec[i].state)) == st) // 已经加进集合 
                     continue ;
                dp[st
| (rec[i].state)] = min(dp[st | (rec[i].state)],dp[st] + rec[i].area);
            }
        }
        printf(
" %d\n " ,dp[( 1 << n) - 1 ]);
    }
    
return   0 ;
}