Go: package main

import (
	"bufio"
	"os"
	"strconv"
	"strings"
	"sort"
	"fmt"
)

var scanner = bufio.NewScanner(os.Stdin)
const INF = 0x7fffffff
func main() {
	scanner.Scan()
	n, _ := strconv.Atoi(scanner.Text())
	top := make([]int, 0)
	bottom := make([]int, 0)
	for i := 0; i < n; i++ {
		scanner.Scan()
		buf := strings.Split(scanner.Text(), " ")
		a, _ := strconv.Atoi(buf[0])
		b, _ := strconv.Atoi(buf[1])
		top = append(top, a)
		bottom = append(bottom, b)
	}
	dp := make([][]int, n+1)
	for i := range dp {
		dp[i] = make([]int, n+1)
	}
	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			dp[i][j] = INF
		}
	}
	for j := 0; j < n; j++ {
		dp[0][j] = 0
	}
	for i := 1; i < n; i++ {
		for j := 0; j < n-i; j++ {
			tmp := make([]int, 0)
			for k := 0; k < i; k++ {
				tmp = append(tmp, dp[k][j] + dp[i - k - 1][j + k + 1] +top[j] * bottom[j + k] * top[j + k + 1] * bottom[j + i])
			}
			sort.Ints(tmp)
			dp[i][j] = tmp[0]
		}
	}
	fmt.Println(dp[n-1][0])
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

Python: #!usr/bin/env python3
import sys
import math
import string
import collections
import fractions
import random
from operator import itemgetter
import itertools
from collections import deque
import copy
import heapq
import bisect

MOD = 10 ** 9 + 7
INF = 10 ** 18
input = lambda: sys.stdin.readline().strip()

sys.setrecursionlimit(10 ** 8)

n = int(input())
a = [1] * n
b = [1] * n
for i in range(n):
    a[i], b[i] = map(int, input().split())

dp = [[INF] * (n + 10) for _ in range(n + 10)]
up = [[1] * (n + 10) for _ in range(n + 10)]
down = [[1] * (n + 10) for _ in range(n + 10)]
for i in range(n):
    dp[i][i] = 0
    up[i][i] = a[i]
    down[i][i] = b[i]
for L in range(n - 2, -1, -1):
    for R in range(L + 1, n):
        dp[L][R] = min(dp[L][i] + dp[i+1][R] + up[L][i] * down[L][i] * up[i + 1][R] * down[i + 1][R] for i in range(L, R))
        for i in range(L, R):
            if dp[L][i] + dp[i+1][R] + up[L][i] * down[L][i] * up[i + 1][R] * down[i + 1][R] == dp[L][R]:
                up[L][R] = up[L][i]
                down[L][R] = down[i + 1][R]
print(dp[0][n - 1])

Python: """
dp[i][j] ... j ~ j + i までまとめた時の最小コスト
dp[0][j] = 0
dp[i][j] = min(dp[k][j] + dp[i - k][j + k + 1] +\
               top[j] * bottom[j + k] * top[j + k + 1] * bottom[j + i] for k in range(i))
"""
INF = 10 ** 20
n = int(input())
top = []
bottom = []
for _ in range(n):
  a, b = map(int, input().split())
  top.append(a)
  bottom.append(b)
dp = [[INF] * (n + 1) for _ in range(n + 1)]
for j in range(n):
  dp[0][j] = 0

for i in range(1, n):
  for j in range(n - i):
    dp[i][j] = min(dp[k][j] + dp[i - k - 1][j + k + 1] +\
                  top[j] * bottom[j + k] * top[j + k + 1] * bottom[j + i] for k in range(i))
print(dp[n - 1][0])

Python: def solve(Card):
  n = len(Card)
  if n==2: return 0
  x=[]
  for i in range(0,n-2,2):
    tmp = Card[:]
    T = tuple(Card[i:i+4])
    if T in d: cost = d[T]
    else:
      cost = reduce(lambda a,b: a*b, T)
      d[T] = cost
    tmp[i+1:i+3]=[]
    x.append(cost+solve(tmp))
  return min(x)

Python: n=int(input())
cards=[]
for i in range(n):
    a,b=map(int,input().split())
    cards.append((a,b))

memo=[[-1 for i in range(n+1)]for j in range(n+1)]
def getans (l,r,cards):
    if(memo[l][r]==-1):
        if(l+1==r):
            memo[l][r]=0
        else:
            ans=1<<32
            for m in range(l+1,r):
                cost=cards[l][0]*cards[m-1][1]*cards[m][0]*cards[r-1][1]+getans(l,m,cards)+getans(m,r,cards)
                ans=min(ans,cost)
            memo[l][r]=ans
    return memo[l][r]

print(getans(0,n,cards))

Python: # AOJ 0145 Cards
# Python3 2018.6.18 bal4u
#　動的計画法　（行列の積に類似）

INF = 0x7fffffff

n = int(input())
c = [[INF for j in range(n)] for i in range(n)]
a = [[0 for j in range(2)] for i in range(n)]

for i in range(n): c[i][i] = 0
for i in range(n): a[i][0], a[i][1] = list(map(int, input().split()))

for l in range(1, n):
	for i in range(n-l):
		j = i + l
		for k in range(i, j):
			c[i][j] = min(c[i][j], c[i][k] +a[i][0]*a[k][1]*a[k+1][0]*a[j][1] +c[k+1][j])

print(c[0][n-1])

C++: #include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <utility>
#include <functional>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <climits>

using namespace std;

inline int toInt(string s) { int v; istringstream sin(s); sin >> v; return v;}
template<class T> inline string toString(T x) { ostringstream sout; sout << x; return sout.str();}

typedef vector<int> vi;
typedef vector<vi>  vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;

#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define EACH(t,i,c) for(t::iretator i=(c).begin(); i!=(c).end(); ++i)
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define REP(i,n) FOR(i,0,n-1)

const double EPS = 1e-10;

int main() {
	int n;
	cin >> n;

	vvi num(n+1, vi(2));
	vvi cost(n+1, vi(n+1, 100000000));

	REP(i, n) {
		cin >> num[i+1][0] >> num[i+1][1];
	}

	REP(i, n+1) {
		cost[1][i] = 0;
	}
	
	FOR(i, 2, n) {
		FOR(j, 1, n-i+1) {
			FOR(k, j, i+j-2) {
				int mul = num[j][0] * num[k][1] * num[k+1][0] * num[i+j-1][1];
				cost[i][j] = min(cost[i][j], mul+cost[k-j+1][j]+cost[i+j-k-1][k+1]);
			}
		}
	}

	cout << cost[n][1] << endl;
	return 0;
}

C++: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;i++)
//#define int long long
using namespace std;

int n;
int top[100], bottom[100];
int dp[100][100];

int rec(int l, int r)
{
	//printf("l = %d, r = %d\n", l, r);
	if (dp[l][r] != -1) return dp[l][r];

	int res = INT_MAX;
	if (l == r)
	{
		res = 0;
	} else if (l + 1 == r) {
		res = top[l] * bottom[l] * top[r] * bottom[r];
	} else {
		//cout << "YES" << endl;
		for (int i=l; i<=r-1; i++)
		{
			res = min(res, rec(l, i) + rec(i + 1, r) + top[l] * bottom[i] * top[i+1] * bottom[r]);
		}
	}

	return dp[l][r] = res;
}

signed main()
{
	cin >> n;
	rep(i,n) cin >> top[i] >> bottom[i];

	memset(dp, -1, sizeof(dp));
	cout << rec(0, n - 1) << endl;
}

C++: #include <vector>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <utility>
#include <functional>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <climits>
using namespace std;
inline int toInt(string s) {int v; istringstream sin(s);sin>>v;return v;}
template<class T> inline string toString(T x) {ostringstream sout;sout<<x;return sout.str();}
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define EACH(t,i,c) for(t::iterator i=(c).begin(); i!=(c).end(); ++i)
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
const double EPS = 1e-10;
const double PI  = acos(-1.0);

ll dp[101][101];
ll a[101],b[101];

const ll MAX=INT_MAX;
ll dfs(int l,int r){
	if(dp[l][r]!=MAX){
		return dp[l][r];
	}
	if(r-l==1){
		return dp[l][r]=min(dp[l][r],a[l]*b[l]*a[r]*b[r]);
	}else if(r==l){
		return dp[l][r]=0;
	}
	ll best=MAX;
	FOR(i,l,r){
		ll cost=a[l]*b[i]*a[i+1]*b[r];
		best=min(best,dfs(l,i)+dfs(i+1,r)+cost);
	}
	return dp[l][r]=min(dp[l][r],best);
}

int main(){
	int n;
	cin>>n;
		REP(i,n+1)REP(j,n+1){
			dp[i][j]=MAX;
		}

		REP(i,n){
			cin>>a[i]>>b[i];
		}

		cout<<dfs(0,n-1)<<endl;
}