Problem:
ハッピーエンド問題
「ハッピーエンド問題」と呼ばれる数学の未解決問題に関連したプログラムを書いてみましょう。平面上に与えられた
N
個の点から、ちょうど
k
個の点を結んでできる凸多角形のうち、最も面積の小さいものを見つけるプログラムを作成してください。ただし、N個の点の座標を与えられた後、質問として凸多角形の角の個数
k
がいくつか与えられます。
（補足：ハッピーエンド問題について）
平面上にどの３点も同じ直線上に乗らないように
N
個の点を置きます。そのとき、どのように点を置いても、k個の点をうまく選ぶとk個の角をもつ凸多角形が必ず作れると予想されています。 今のところ、三角形ならば
N
=3、四角形ならば
N
=5、五角形ならば
N
=9、六角形ならば
N
=17であればよいことが、２００６年までに証明されています。また、三角形以上のすべてのk角形に対して、
N
=1+2
k
-2
という予想がありますが、いまだ証明されていません。これは１００年にわたり研究が進められている難問です。
この問題には、「ハッピーエンド問題」という素敵な名前がつけられています。ある男女がこの問題を研究しているうちに仲良くなって、ついに結婚したことにちなんで、友人の数学者が名付けたそうです。ロマンチックですね。
入力
入力は1つのデータセットからなる。入力データは以下の形式で与えられる。
N
x
1
y
1
:
x
N
y
N
Q
k
1
:
k
Q
１行目に平面上の点の個数
N
(3 ≤
N
≤ 40)が与えられる。続く
N
行に各点の座標が与えられる。各点には1から
N
までの番号が、入力される順番に付けられている。
x
i
と
y
i
(-10000 ≤
x
i
,
y
i
≤ 10000)は
i
番目の点のそれぞれ
x
座標と
y
座標を表す整数である。
x
軸の正方向は右向き,
y
軸の正方向は上向きに取るものとする。
続く１行に質問の数
Q
(1 ≤
Q
≤
N
)が与えられる。続く
Q
行に質問が与えられる。
k
i
(3 ≤
k
i
≤
N
)は
i
番目の質問である凸多角形の角の個数を表す。
なお、入力は以下の条件を満たすものとする。
入力される点の座標はすべて異なる。
どの３点も同じ直線上には乗らない。
各質問に対して面積最小の凸多角形は１つであり、２番目に小さい凸多角形との面積の差は 0.0001以上。
出力
質問ごとに、面積が最小の凸多角形の全頂点を1行に出力する。凸多角形の頂点で最も下にあるものの中で最も左にある頂点から順に、反時計周りで頂点の番号を出力する。頂点の番号の間は空白1つで区切る。行の終わりには空白文字を出力しない。ただし、凸多角形が作れない場合はNAと出力する。
入力例 1
5
0 0
3 0
5 2
1 4
0 3
3
3
4
5
出力例 1
1 4 5
1 2 4 5
1 2 3 4 5
入力例 2
6
0 0
3 0
5 2
1 4
0 3
3 2
4
3
4
5
6
出力例 2
6 3 5
6 3 4 5
1 2 6 4 5
NA

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ld=long double;
#define fi first;
#define se second;
#define i128 __int128_t
#define all(x) x.begin(),x.end()
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define si(a) (long)(a.size())
template<typename T>bool chmin(T&a,T b){return b<a?(a=b,1):0;}
template<typename T>bool chmax(T&a,T b){return b>a?(a=b,1):0;}
const int INF=1e9+100;
const long INFL=3e18+100;
struct _ {
   _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0); }
} __;

namespace geometry{
    using Real = long double;
    using Point = complex<Real>;
    const Real EPS = 1e-12;
    const Real PI = acos(-1);
    inline bool equal(const Real& a, const Real& b){
        return fabs(a - b) < EPS;
    }
    Real dot(const Point &a, const Point &b){
        return (a.real() * b.real() + a.imag() * b.imag());
    }
    Real cross(const Point &a, const Point &b){
        return (a.real() * b.imag() - a.imag() * b.real());
    }
    inline int sign(const Real &r) { return r <= -EPS ? -1 : r >= EPS ? 1 : 0; }
    int ccw(const Point &a, const Point &b, const Point &c){
        Point d = b - a;
        Point e = c - a;
        if(cross(d, e) > EPS) return 1; // counter clockwise (反時計回り)
        if(cross(d, e) < -EPS) return -1; // clockwise (時計回り)
        if(dot(d, e) < 0) return 2; // c-b-a
        if(norm(d) < norm(e)) return -2; // a-b-c
        return 0; // a-c-b
    }
    Real area3(Point a, Point b, Point c){
        return abs(cross(b-a,c-a))/2;
    }
}
using namespace geometry;


ld dp[50][50][50][50];
int pre[50][50][50][50];
int main(){

    rep(i,50)rep(j,50)rep(k,50)rep(l,50) dp[i][j][k][l]=INFL, pre[i][j][k][l]=-1;

    int N;
    cin>>N;
    vector<Point> P(N);
    rep(i,N){
        int x,y;
        cin>>x>>y;
        P[i]=Point(x,y);
    }

    vector<ld> mi(N+1,INFL);
    vector<vector<int>> ans(N+1);


    rep(s,N){
        auto fs=[&](int i)->bool {
            if(P[i].imag()==P[s].imag()) return P[i].real()>=P[s].real();
            return P[i].imag()>P[s].imag();
        };
        rep(e, N){
            if(!fs(e)) continue;
            dp[s][1][e][s]=0;
        }
        rep(k,N){
            rep(i,N){
                if(i==s) continue;
                rep(j,N){
                    if(i==j) continue;
                    if(dp[s][k][i][j]>=INFL) continue;
                    rep(e,N){
                        if(i==e||j==e) continue;
                        if(!fs(e)) continue;
                        if(ccw(P[j], P[i], P[e])!=-1) continue;
                        if(e!=s&&ccw(P[i], P[e], P[s])!=-1) continue;
                        
                        if(chmin(dp[s][k+1][e][i], dp[s][k][i][j]+area3(P[s], P[e], P[i]))){
                            pre[s][k+1][e][i]=j;
                        }
                    }
                }
            }

            rep(j,N){
                if(chmin(mi[k+1], dp[s][k+1][s][j])){
                    vector<int> V;
                    int ni=s;
                    int nj=j;
                    for(int l=k+1;l>=1;l--){
                        V.push_back(ni);
                        int tmp=pre[s][l][ni][nj];
                        ni=nj;
                        nj=tmp;
                    }
                    ans[k+1]=V;
                }
            }
        }
    }

    int Q;
    cin>>Q;
    while(Q--){
        int k;
        cin>>k;
        if(si(ans[k])!=k) cout<<"NA\n";
        else rep(i,k) cout<<ans[k][i]+1<<(i==k-1?"\n":" ");
    }
}
accuracy: 1
time_ms: 30
memory_kb: 125500
final_rank: 12

code_snippet: #include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;
long double xs[43];
long double ys[43];

class E{
	public:
	long double s1;
	vector<int> v1;
	E(){
		s1=-1;
		v1.clear();
	}
};

E ans[42];



long double g(int p1,int p2,int p3){
	long double x2,y2,x3,y3;
	x2=xs[p2]-xs[p1];
	y2=ys[p2]-ys[p1];
	x3=xs[p3]-xs[p1];
	y3=ys[p3]-ys[p1];
	return x2*y3-x3*y2;
}

bool allok(vector<int> &v1){
	int n=v1.size();
	int p1=v1[n-2];
	int p2=v1[n-1];
	int p3=v1[0];
	if(g(p1,p2,p3)<0)return false;
	return true;
}

bool f2(int i,int j){
	if (ys[i]==ys[j] && xs[i]<xs[j]){
		return true;
	}else if(ys[i]<ys[j]){
		return true;
	}
	return false;
}
void f4(int p1,int p2,int n){
	
	E dp[42][42][42];
	
	E e1;
	e1.v1.push_back(p1);
	e1.v1.push_back(p2);
	e1.s1=0;
	dp[2][p1][p2]=e1;
	for(int i=2;i<n;i++){
		for(int t1=0;t1<n;t1++){
			for(int t2=0;t2<n;t2++){
				if(t1==t2)continue;
				E e1=dp[i][t1][t2];
				if(e1.s1<0)continue;
				for(int t3=0;t3<n;t3++){
					if(t1==t3||t2==t3)continue;
					if(0>=g(t1,t2,t3))continue;
					if(find(e1.v1.begin(),e1.v1.end(),t3)==e1.v1.end() && f2(e1.v1[0],t3)==true){
						long double s1=g(e1.v1[0],t2,t3);
						if(s1<0)continue;
						e1.v1.push_back(t3);
						if (allok(e1.v1)==false){
							e1.v1.pop_back();
							continue;
						}
						
						long double s3=e1.s1;
						e1.s1+=abs(s1);
						long double s4=dp[i+1][t2][t3].s1;
						if(ans[i+1].s1<0 ||ans[i+1].s1>e1.s1){
							ans[i+1]=e1;
							if(i+1==4){
								
							}
						}
						if(s4<0 || s4>e1.s1){
							dp[i+1][t2][t3]=e1;
						}
						e1.v1.pop_back();
						e1.s1=s3;
					}
				}
			}
		}
	}
	
}

void f3(int n){
	for(int i=0;i<=n;i++){
		ans[i].s1=-1;
	}
	for(int i=0;i<n;i++){
		cin>>xs[i]>>ys[i];
	}
	for(int p1=0;p1<n;p1++){
		for(int p2=0;p2<n;p2++){
			if((p1==p2)||(f2(p1,p2)==false))continue;
			f4(p1,p2,n);
		}
	}
	int m;
	cin>>m;
	for(int i=0;i<m;i++){
		int t;
		cin>>t;
		if(ans[t].s1==-1){
			cout<<"NA"<<endl;
		}else{
			cout<<ans[t].v1[0]+1;
			for(int i=1;i<t;i++){
				cout<<" "<<ans[t].v1[i]+1;
			}
			cout<<endl;
		}
		
	}
}


int main() {
	// your code goes here
	int n;
	cin>>n;
	f3(n);
	return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 6988
final_rank: 10

code_snippet: //#pragma GCC target ("avx2")
//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define _USE_MATH_DEFINES
#include<iostream>
#include<string>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<list>
#include<iomanip>
#include<vector>
#include<random>
#include<functional>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<unordered_map>
#include<climits>
#include<fstream>
#include<complex>
#include<time.h>
#include<cassert>
#include<functional>
#include<numeric>
#include<tuple>
using namespace std;
using ll = long long;
using ld = long double;
using H = pair<ll, ll>;
using P = pair<ll, H>;
using vi = vector<ll>;
#define all(a) (a).begin(),(a).end()
#define fs first
#define sc second
#define xx first
#define yy second.first
#define zz second.second
#define Q(i,j,k) mkp((i),mkp((j),(k)))
#define rng(i,s,n) for(ll i = (s) ; i < (n) ; i++)
#define rep(i,n) rng(i, 0, (n))
#define mkp make_pair
#define vec vector
#define pb emplace_back
#define siz(a) int((a).size())
#define crdcomp(b) sort(all((b)));(b).erase(unique(all((b))),(b).end())
#define getidx(b,i) (lower_bound(all((b)),(i))-(b).begin())
#define ssp(i,n) (i==(ll)(n)-1?"\n":" ")
#define ctoi(c) (int)((c)-'0')
#define itoc(c) (char)((c)+'0')
#define cyes printf("Yes\n")
#define cno printf("No\n")
#define cdf(n) for(int quetimes_=(n);quetimes_>0;quetimes_--)
#define gcj printf("Case #%lld: ",quetimes_+1)
#define readv(a,n) (a).resize((n),0);rep(i,(n)) (a)[i]=read()
#define found(a,x) (a.find(x)!=a.end())
constexpr ll mod = (ll)1e9 + 7;
constexpr ll Mod = 998244353;
constexpr ld EPS = 1e-10;
constexpr ll inf = (ll)3 * 1e18;
constexpr int Inf = (ll)15 * 1e8;
constexpr int dx[] = { -1,1,0,0 }, dy[] = { 0,0,-1,1 };
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
ll read() { ll u, k = scanf("%lld", &u); return u; }
string reads() { string s; cin >> s; return s; }
H readh(short g = 0) { H u; int k = scanf("%lld %lld", &u.fs, &u.sc); if (g == 1) u.fs--, u.sc--; if (g == 2) u.fs--; return u; }
bool ina(H t, int h, int w) { return 0 <= t.fs && t.fs < h && 0 <= t.sc && t.sc < w; }
bool ina(int t, int l, int r) { return l <= t && t < r; }
ll gcd(ll i, ll j) { return j ? gcd(j, i % j) : i; }
ll ppc(ll x) {
    int sum = 0; for (int i = 0; i < 60; i++)if ((1ll << i) & x) sum++;
    return sum;
}
template<typename T>
void fin(T x) { cout << x << endl; exit(0); }

template<typename T>
class csum {
    vec<T> v;
public:
    csum(vec<T>& a) :v(a) { build(); }
    csum() {}
    csum(int sz) { init(sz); }
    void init(int sz) { v = vector<T>(sz + 1, 0); }
    void init(vec<T>& a) { v = a; build(); }
    void build() {
        for (int i = 1; i < v.size(); i++) v[i] += v[i - 1];
    }
    void add(int l, int r, T x) {
        v[l] += x;
        v[r] -= x;
    }//[l,r)
    void add(int t, T x) {
        v[t] += x;
    }//[l,r)
    //[l,r]
    T a(int l, int r) {
        if (r < l) return 0;
        return v[r] - (l == 0 ? 0 : v[l - 1]);
    }
    //[l,r)
    T b(int l, int r) {
        return a(l, r - 1);
    }
    T a(pair<int, int>t) {
        return a(t.first, t.second);
    }
    T b(pair<int, int>t) {
        return b(t.first, t.second);
    }
    T operator[](int x)const {
        return v[x];
    }
};
class via {
    using H = pair<ll, ll>;
    bool comp;
public:
    vector<H>a;
    via() :comp(true) {}
    via(vector<H>dat) :a(dat), comp(false) { build(); }
    void push(int l, int r) { a.push_back(H{ l,r }); comp = false; }
    void push(H a) { push(a.first, a.second); }
    void build() {
        if (comp) return;
        comp = true;
        sort(a.begin(), a.end());
        int fst = -1; ll lst = -1;
        vector<H>b;
        for (int i = 0; i < a.size(); i++) {
            if (fst < 0) fst = i, lst = a[i].second;
            if (lst < a[i].first) {
                b.push_back(H{ a[fst].first,lst });
                fst = i, lst = a[i].second;
            }
            else if (lst < a[i].second) lst = a[i].second;
        }
        if (~fst) b.push_back(H{ a[fst].first, lst });
        a = b;
    }
    ll size() { return ll(a.size()); }
    ll sum() {
        build();
        ll sum = 0;
        for (auto g : a) sum += g.second - g.first;
        return sum;
    }
    via inter(via& v) {
        build(); v.build();
        via ret;
        for (auto g : a) ret.push(g);
        for (auto g : v.a) ret.push(g);
        ret.build(); return ret;
    }
    via comb(via& v) {
        build(); v.build();
        int s = 0, t = 0;
        via ret;
        while (s < a.size() && t < v.size()) {
            if (v[t].second <= a[s].first)  t++;
            else if (a[s].second <= v[t].first) s++;
            else {
                ret.push(max(a[s].first, v[t].first), min(a[s].second, v[t].second));
                if (a[s].second <= v[t].second) s++;
                else t++;
            }
        }
        return ret;
    }
    H& operator[](int t) { return a[t]; }
};
template<ll mod>
class modint {
public:ll v;
      modint(ll v = 0) { s(v % mod + mod); }
      constexpr static int fn_ = (ll)2e6 + 5;
      static vector<modint>fact, comp;
      modint pow(ll x) const {
          modint b(v), c(1);
          while (x) {
              if (x & 1) c *= b;
              b *= b;
              x >>= 1;
          }
          return c;
      }
      inline modint& s(int vv) {
          v = vv < mod ? vv : vv - mod;
          return *this;
      }
      inline modint inv()const { return pow(mod - 2); }
      inline modint operator-()const { return modint() - *this; }
      inline modint& operator+=(const modint b) { return s(v + b.v); }
      inline modint& operator-=(const modint b) { return s(v + mod - b.v); }
      inline modint& operator*=(const modint b) { v = v * b.v % mod; return *this; }
      inline modint& operator/=(const modint b) { v = v * b.inv().v % mod; return *this; }
      inline modint operator+(const modint& b) const { return modint(v) += b; }
      inline modint operator-(const modint& b) const { return modint(v) -= b; }
      inline modint operator*(const modint& b) const { return modint(v) *= b; }
      inline modint operator/(const modint& b) const { return modint(v) /= b; }
      friend ostream& operator<<(ostream& os, const modint& m) {
          return os << m.v;
      }
      friend istream& operator>>(istream& is, modint& m) {
          int x; is >> x; m = modint(x);
          return is;
      }
      bool operator<(const modint& r)const { return v < r.v; }
      bool operator>(const modint& r)const { return v > r.v; }
      bool operator<=(const modint& r)const { return v <= r.v; }
      bool operator>=(const modint& r)const { return v >= r.v; }
      bool operator==(const modint& r)const { return v == r.v; }
      bool operator!=(const modint& r)const { return v != r.v; }
      explicit operator bool()const { return v; }
      explicit operator int()const { return v; }
      modint comb(modint k) {
          if (k > *this) return modint();
          if (fact.empty()) combinit();
          if (v >= fn_) {
              if (k > *this - k) k = *this - k;
              modint tmp(1);
              for (int i = v; i >= v - k.v + 1; i--) tmp *= modint(i);
              return tmp * comp[k.v];
          }
          return fact[v] * comp[k.v] * comp[v - k.v];
      }//nCk
      modint perm(modint k) {
          if (k > *this) return modint();
          if (fact.empty()) combinit();
          if (v >= fn_) {
              modint tmp(1);
              for (int i = v; i >= v - k.v + 1; i--) tmp *= modint(i);
              return tmp;
          }
          return fact[v] * comp[v - k.v];
      }//nPk
      static void combinit() {
          fact.assign(fn_, modint());
          fact[0] = 1;
          for (int i = 1; i < fn_; i++) fact[i] = fact[i - 1] * modint(i);
          comp.assign(fn_, modint());
          comp[fn_ - 1] = fact[fn_ - 1].inv();
          for (int i = fn_ - 2; i >= 0; i--) comp[i] = comp[i + 1] * modint(i + 1);
      }
};
using mint = modint<ll(1e9 + 7)>; template<>vec<mint> mint::fact = vec<mint>(); template<>vec<mint> mint::comp = vec<mint>();
//--------------------------------------------------------------
//--------------------------------------------------------------
ll area(H a, H b, H c) {
    b.fs -= a.fs; b.sc -= a.sc;
    c.fs -= a.fs; c.sc -= a.sc;
    return b.fs * c.sc - b.sc * c.fs;
}


ll dp[42][42][42][42];

signed main() {
    int n; cin >> n;
    vec<H>a;
    rep(i, n) a.pb(readh());

    vec<vec<H>>ans(n + 1, vec<H>());
    vi score(n + 1, inf);

    rep(st, n) {
        //start is st

        vec<H>b;
        rep(i, n) if (a[i].fs >= a[st].fs && a[i] != a[st]) b.pb(a[i]);
        sort(all(b), [&](H x, H y) {
            return area(a[st], x, y) < 0;
            });

        rep(i, 42)rep(j, 42)rep(k, 42)rep(t, 42) dp[i][j][k][t] = inf;
        
        rep(i, siz(b))rng(j, i + 1, siz(b)) {
            dp[j][3][i][j] = -area(a[st], b[i], b[j]);
        }

        rng(i, 2, siz(b)) {
            rng(j, 3, i + 3) {
                rep(x, i)rng(y, x + 1, i) {
                    dp[i][j][x][y] = dp[i - 1][j][x][y];
                    if (dp[i - 1][j - 1][x][y] < inf) {
                        if (area(b[x], b[y], b[i]) < 0) {
                            chmin(dp[i][j][y][i], dp[i - 1][j - 1][x][y] - area(a[st], b[y], b[i]));
                        }
                    }
                }
            }
        }

        rng(z, 3, siz(b) + 2) {
            int i = siz(b) - 1, j = z, x = -1, y = 0;
            rep(k, siz(b))rep(t, siz(b)) {
                if (x < 0 && dp[i][j][k][t] < inf) x = k, y = t;
                else if (~x && dp[i][j][x][y] > dp[i][j][k][t]) {
                    x = k, y = t;
                }
            }
            if (x < 0) continue;
            vec<H>v; v.pb(b[y]); v.pb(b[x]); v.pb(a[st]);
            ll rest = dp[i][j][x][y];
            rest += area(a[st], b[x], b[y]);

            if (score[j] <= dp[i][j][x][y]) continue;
            score[j] = dp[i][j][x][y];

            while (rest > 0) {
                rep(k, siz(b)) {
                    if (area(b[k], b[x], b[y]) < 0 &&
                        dp[x][j - 1][k][x] - area(a[st], b[x], b[y]) ==
                        dp[y][j][x][y]) {
                        v.pb(b[k]);
                        rest += area(a[st], b[k], b[x]);
                        y = x; x = k;
                        j--;
                        break;
                    }
                }
            }

            ans[z] = v;
        }
    }

    map<H, int>mp;
    rep(i, n) mp[a[i]] = i + 1;
    vec<vi>ans2(n + 1);
    rep(i, n + 1) {
        if (siz(ans[i]) == 0) continue;
        int st = 0;
        vi tmp;
        rep(j, siz(ans[i]))
            if (ans[i][st].sc > ans[i][j].sc ||
                ans[i][st].sc == ans[i][j].sc &&
                ans[i][st].fs > ans[i][j].fs)
                st = j;
        tmp.pb(mp[ans[i][st]]);
        vec<H>c;
        rep(j, siz(ans[i])) if (ans[i][j] != ans[i][st]) c.pb(ans[i][j]);
        sort(all(c), [&](H x, H y) {
            return area(ans[i][st], x, y) > 0;
            });
        for (auto g : c) tmp.pb(mp[g]);
        ans2[i] = tmp;
    }
    
    int q; cin >> q;
    rep(i, q) {
        int t; cin >> t;
        if (siz(ans2[t]) == 0) cout << "NA\n";
        else {
            rep(j, siz(ans2[t])) cout << ans2[t][j] << ssp(j, siz(ans2[t]));
        }
    }
}
accuracy: 1
time_ms: 60
memory_kb: 27836
final_rank: 9

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

using real = int;
struct Point {
    real x, y;
    Point& operator+=(const Point a) { x += a.x; y += a.y;  return *this; }
    Point& operator-=(const Point a) { x -= a.x; y -= a.y;  return *this; }
    Point& operator*=(const real k) { x *= k; y *= k;  return *this; }
    Point& operator/=(const real k) { x /= k; y /= k;  return *this; }
    Point operator+(const Point a) const {return Point(*this) += a; }
    Point operator-(const Point a) const {return Point(*this) -= a; }
    Point operator*(const real k) const {return Point(*this) *= k; }
    Point operator/(const real k) const {return Point(*this) /= k; }
    bool operator<(const Point &a) const { return (x != a.x ? x < a.x : y < a.y); }
    explicit Point(real a = 0, real b = 0) : x(a), y(b) {};
};

istream& operator>> (istream& s, Point& P){
    s >> P.x >> P.y;
    return s;
}




template <class T, class U>
vector<T> make_v(U size, const T& init){ return vector<T>(static_cast<size_t>(size), init); }

template<class... Ts, class U>
auto make_v(U size, Ts... rest) { return vector<decltype(make_v(rest...))>(static_cast<size_t>(size), make_v(rest...)); }

template<class T> void chmin(T &a, const T &b){ a = (a < b ? a : b); }
template<class T> void chmax(T &a, const T &b){ a = (a > b ? a : b); }



// dp[i][j][k][l]  := 三角形jklから隣接してできた凸i角形
// prv[i][j][k][l] := 三角形ijkから凸i角形を作るときに追加する点k
int dp[41][40][40][40], prv[41][40][40][40];

int main() {
    int n;
    cin >> n;
    vector<Point> v(n);
    for (int i = 0; i < n; ++i) {
        cin >> v[i];
    }
    auto area = [](Point a, Point b, Point c){ return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); };
    auto to = make_v(n, n, vector<int>());
    fill_n((int*)dp, 41*40*40*40, INF<int>);
    fill_n((int*)prv, 41*40*40*40, 0);

    // 線ijから三角形ijkを作れる点kを求める
    // 新しく追加する点はjよりも低い位置にあることが条件
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if(i == j) continue;
            if(v[i].y <= v[j].y) dp[2][i][i][j] = 0;
            for (int k = 0; k < n; ++k) {
                if(i == k || j == k) continue;
                if(area(v[i], v[j], v[k]) > 0 && (v[i].y <= v[j].y || v[j].y >= v[k].y)){
                    to[i][j].emplace_back(k);
                }
            }
        }
    }
    for (int i = 2; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                for (int l = 0; l < n; ++l) {
                    if(dp[i][j][k][l] == INF<int>) continue;
                    for (auto &&m : to[k][l]) {
                        if(v[j].y > v[m].y || j == m) continue;
                        int a = area(v[j], v[l], v[m]);

                        if(a > 0 && dp[i+1][j][l][m] > dp[i][j][k][l]+a){
                            dp[i+1][j][l][m] = dp[i][j][k][l]+a;
                            prv[i+1][j][l][m] = k;
                        }
                    }
                }
            }
        }
    }
    vector<vector<int>> anss(n+1);
    // 凸i角形の最小のものを求める
    for (int i = 3; i <= n; ++i) {
        int val = INF<int>, a = 0, b = 0, c = 0;
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                for (int l = 0; l < n; ++l) {
                    if(dp[i][j][k][l] < val){
                        val = dp[i][j][k][l];
                        a = j; b = k; c = l;
                    }
                }
            }
        }
        if(val == INF<int>) {
            continue;
        }
        // prvから点kを取り出す
        vector<int> ans{c, b};
        for (int j = i; j >= 3; --j) {
            int x = prv[j][a][b][c];
            ans.emplace_back(x);
            c = b; b = x;
        }

        // 反時計回りにする
        reverse(ans.begin(),ans.end());
        if(v[ans.front()].y == v[ans.back()].y){
            rotate(ans.begin(), ans.end()-1, ans.end());
        }
        anss[i] = ans;
    }
    int q;
    cin >> q;
    while(q--){
        int x;
        cin >> x;
        if(anss[x].empty()) puts("NA");
        else{
            for (int i = 0; i < anss[x].size(); ++i) {
                printf(i ? " %d" : "%d", anss[x][i]+1);
            }
            puts("");
        }
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 24168
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

// template {{{
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;

#define  range(i, l, r) for (i64 i = (i64)(l); i < (i64)(r); (i) += 1)
#define rrange(i, l, r) for (i64 i = (i64)(r) - 1; i >= (i64)(l); (i) -= 1)

#define  whole(f, x, ...) ([&](decltype((x)) container) { return (f)(  begin(container),  end(container), ## __VA_ARGS__); })(x)
#define rwhole(f, x, ...) ([&](decltype((x)) container) { return (f)( rbegin(container), rend(container), ## __VA_ARGS__); })(x)

#define debug(x) cerr << "(" << __LINE__ << ")" << #x << ": " << (x) << endl

constexpr i32 inf   = 1001001001;
constexpr i64 infll = 1001001001001001001ll;

constexpr i32 dx[] = {0, -1, 1, 0, -1, 1, -1, 1}; 
constexpr i32 dy[] = {-1, 0, 0, 1, -1, -1, 1, 1};

struct IoSetup { IoSetup(i32 x = 15){ cin.tie(0); ios::sync_with_stdio(0); cout << fixed << setprecision(x); cerr << fixed << setprecision(x); } } iosetup;

template <typename T = i64> T input() { T x; cin >> x; return x; }

template <typename T> ostream &operator<<(ostream &os, vector<T> &v) { range(i, 0, v.size()) { os << v[i] << (i + 1 != (int)v.size() ? " " : ""); } return os; } 
template <typename T> istream &operator>>(istream &is, vector<T> &v) { for (T &in : v) is >> in; return is; }

template <typename T1, typename T2> ostream &operator<<(ostream &os, pair<T1, T2> p) { os << "(" << p.first << ", " << p.second << ")"; return os; }
template <typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &p) { is >> p.first >> p.second; return is; }

template <typename T> vector<T> make_vector(size_t a, T b) { return vector<T>(a, b); }
template <typename... Ts> auto make_vector(size_t a, Ts... ts) { return vector<decltype(make_vector(ts...))>(a, make_vector(ts...)); }

template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }
// }}}

// base
namespace geometry {
  using namespace std;
  using real_number = double;
  // using real_number = long double;

  const real_number PI = acosl(-1);

  inline static real_number &eps() {
    static real_number EPS = 1e-10;
    return EPS;
  }

  static void set_eps(real_number EPS) {
    eps() = EPS;
  }

  inline int sign(real_number r) {
    set_eps(1e-10);
    if (r < -eps()) return -1;
    if (r > +eps()) return +1;
    return 0;
  }

  inline bool equals(real_number r1, real_number r2) {
    return sign(r1 - r2) == 0;
  }
}

// point
namespace geometry {
  using point = complex< real_number >;
  using points = vector< point >;

  istream &operator>>(istream &is, point &p) {
    real_number x, y;
    is >> x >> y;
    p = point(x, y);
    return is;
  }

  ostream &operator<<(ostream &os, const point &p) {
    return os << p.real() << " " << p.imag();
  }

  point operator*(const point &p, const real_number &k) {
    return point(p.real() * k, p.imag() * k);
  }

  point rotate(const real_number &theta, const point &p) {
    return point(cos(theta) * p.real() + sin(-theta) * p.imag(),
                 sin(theta) * p.real() + cos(-theta) * p.imag());
  }

  bool equals(const point &a, const point &b) {
    return equals(a.real(), b.real()) and equals(a.imag(), b.imag());
  }
}

namespace geometry {
  bool compare_x(const point &a, const point &b) {
    return !equals(a.real(), b.real()) ? a.real() < b.real() : a.imag() < b.imag();
  }

  bool compare_y(const point &a, const point &b) {
    return !equals(a.imag(), b.imag()) ? a.imag() < b.imag() : a.real() < b.real();
  }
}

// product
namespace geometry {
  real_number cross(const point &a, const point &b) {
    return a.real() * b.imag() - a.imag() * b.real();
  }

  real_number dot(const point &a, const point &b) {
    return a.real() * b.real() + a.imag() * b.imag();
  }
}

// ccw
namespace geometry {
  constexpr int COUNTER_CLOCKWISE = +1;
  constexpr int CLOCKWISE         = -1;
  constexpr int ONLINE_BACK       = +2; // c-a-b
  constexpr int ONLINE_FRONT      = -2; // a-b-c
  constexpr int ON_SEGMENT        =  0; // a-c-b
  int ccw(const point &a, point b, point c) {
    b = b - a, c = c - a;
    if (sign(cross(b, c)) == +1) return COUNTER_CLOCKWISE;
    if (sign(cross(b, c)) == -1) return CLOCKWISE;
    if (sign(dot(b, c)) == -1) return ONLINE_BACK;
    if (norm(b) < norm(c)) return ONLINE_FRONT;
    return ON_SEGMENT;
  }
}

// polygon
namespace geometry {
  using polygon = vector< point >;
  using polygons = vector< polygon >;
}

// area
namespace geometry {
  real_number area(const polygon &poly) {
    int n = poly.size();
    real_number res = 0;
    for (int i = 0; i < n; ++i) {
      res += cross(poly[i], poly[(i + 1) % n]);
    }
    return res / 2;
  }
}

using namespace geometry;

void solve() {
  int n = input();
  
  vector< pair<point, int> > pts;
  range(i, 0, n) {
    point p;
    cin >> p;
    pts.emplace_back(p, i + 1);
  }

  whole(sort, pts, [](auto &a, auto &b) { return compare_x(a.first, b.first); });

  auto udp = make_vector(n, n, n, n + 1, real_number(inf));
  auto uval = make_vector(n, n, n, n + 1, pair<int, int>(-1, -1));
  range(s, 0, n) range(t, s + 1, n) {
    udp[s][s][t][2] = 0;
  }

  range(s, 0, n) range(p, s, n) range(t, p + 1, n) range(k, 2, n) {
    point q = pts[s].first;

    point a = pts[p].first;
    point b = pts[t].first;

    if (udp[s][p][t][k] > inf - 1) continue;
    range(i, t + 1, n) {
      point c = pts[i].first;
      if (ccw(a, b, c) != CLOCKWISE) continue;
      polygon poly({q, b, c});
      real_number S = abs(area(poly));

      if (sign(udp[s][t][i][k + 1] - (udp[s][p][t][k] + S)) > 0) {
        udp[s][t][i][k + 1] = udp[s][p][t][k] + S;
        uval[s][t][i][k + 1] = make_pair(p, t);
      }
    }
  }

  auto ddp = make_vector(n, n, n, n + 1, real_number(inf));
  auto dval = make_vector(n, n, n, n + 1, pair<int, int>(-1, -1));
  range(s, 0, n) range(t, s + 1, n) {
    ddp[s][s][t][2] = 0;
  }

  range(s, 0, n) range(p, s, n) range(t, p + 1, n) range(k, 2, n) {
    point q = pts[s].first;
    
    point a = pts[p].first;
    point b = pts[t].first;

    if (ddp[s][p][t][k] > inf - 1) continue;
    range(i, t + 1, n) {
      point c = pts[i].first;
      if (ccw(a, b, c) != COUNTER_CLOCKWISE) continue;
      polygon poly({q, b, c});
      real_number S = abs(area(poly));

      if (sign(ddp[s][t][i][k + 1] - (ddp[s][p][t][k] + S)) > 0) {
        ddp[s][t][i][k + 1] = ddp[s][p][t][k] + S;
        dval[s][t][i][k + 1] = make_pair(p, t);
      }
    }
  }

  auto upre = make_vector(n, n, n + 1, -1);
  range(s, 0, n) range(t, s + 1, n) range(k, 2, n + 1) {
    int &idx = upre[s][t][k];
    range(p, s, t) {
      if (udp[s][p][t][k] > inf - 1) continue;
      if (idx == -1 or sign(udp[s][idx][t][k] - udp[s][p][t][k]) > 0) {
        idx = p;
      }
    }
  }

  auto dpre = make_vector(n, n, n + 1, -1);
  range(s, 0, n) range(t, s + 1, n) range(k, 2, n + 1) {
    int &idx = dpre[s][t][k];
    range(p, s, t) {
      if (ddp[s][p][t][k] > inf - 1) continue;
      if (idx == -1 or sign(ddp[s][idx][t][k] - ddp[s][p][t][k]) > 0) {
        idx = p;
      }
    }
  }

  int q = input();
  range(_, 0, q) {
    int k = input();

    real_number min_area = inf;
    int S = -1, T = -1, A = -1, P = -1, Q = -1;
    range(s, 0, n) range(t, s + 1, n) range(a, 2, k + 1) {
      int b = k + 2 - a;

      int p = upre[s][t][a];
      int q = dpre[s][t][b];

      if (p == -1 or q == -1) continue;

      real_number now_area = udp[s][p][t][a] + ddp[s][q][t][b];
      if (sign(min_area - now_area) <= 0) continue;
      min_area = now_area;
      S = s;
      T = t;
      A = a;
      P = p;
      Q = q;
    }

    if (S == -1) {
      cout << "NA" << endl;
      continue;
    }

    vector< int > idxs;
    {
      int p = Q, t = T, a = k + 2 - A;
      while (true) {
        idxs.emplace_back(t);
        if (p == S) break;
        tie(p, t) = dval[S][p][t][a];
        a--;
      }
    }

    whole(reverse, idxs);
    idxs.pop_back();

    {
      int p = P, t = T, a = A;
      while (true) {
        idxs.emplace_back(t);
        if (p == S) break;
        tie(p, t) = uval[S][p][t][a];
        a--;
      }
    }

    idxs.emplace_back(S);

    int st = 0;
    range(i, 1, idxs.size()) {
      point a = pts[idxs[i]].first;
      point pt = pts[idxs[st]].first;
      if (pt.imag() < a.imag()) continue;
      if (pt.imag() > a.imag()) {
        st = i;
        continue;
      }
      if (pt.real() > a.real()) {
        st = i;
      }
    }

    vector< int > ans;
    range(i, 0, idxs.size()) {
      ans.emplace_back(pts[idxs[(i + st) % idxs.size()]].second);
    }

    cout << ans << endl;
  }
}

signed main() {
  solve();
}
accuracy: 1
time_ms: 50
memory_kb: 93920
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

// template {{{
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;

#define  range(i, l, r) for (i64 i = (i64)(l); i < (i64)(r); (i) += 1)
#define rrange(i, l, r) for (i64 i = (i64)(r) - 1; i >= (i64)(l); (i) -= 1)

#define  whole(f, x, ...) ([&](decltype((x)) container) { return (f)(  begin(container),  end(container), ## __VA_ARGS__); })(x)
#define rwhole(f, x, ...) ([&](decltype((x)) container) { return (f)( rbegin(container), rend(container), ## __VA_ARGS__); })(x)

#define debug(x) cerr << "(" << __LINE__ << ")" << #x << ": " << (x) << endl

constexpr i32 inf   = 1001001001;
constexpr i64 infll = 1001001001001001001ll;

constexpr i32 dx[] = {0, -1, 1, 0, -1, 1, -1, 1}; 
constexpr i32 dy[] = {-1, 0, 0, 1, -1, -1, 1, 1};

struct IoSetup { IoSetup(i32 x = 15){ cin.tie(0); ios::sync_with_stdio(0); cout << fixed << setprecision(x); cerr << fixed << setprecision(x); } } iosetup;

template <typename T = i64> T input() { T x; cin >> x; return x; }

template <typename T> ostream &operator<<(ostream &os, vector<T> &v) { range(i, 0, v.size()) { os << v[i] << (i + 1 != (int)v.size() ? " " : ""); } return os; } 
template <typename T> istream &operator>>(istream &is, vector<T> &v) { for (T &in : v) is >> in; return is; }

template <typename T1, typename T2> ostream &operator<<(ostream &os, pair<T1, T2> p) { os << "(" << p.first << ", " << p.second << ")"; return os; }
template <typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &p) { is >> p.first >> p.second; return is; }

template <typename T> vector<T> make_vector(size_t a, T b) { return vector<T>(a, b); }
template <typename... Ts> auto make_vector(size_t a, Ts... ts) { return vector<decltype(make_vector(ts...))>(a, make_vector(ts...)); }

template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }
// }}}

// base
namespace geometry {
  using namespace std;
  using real_number = long double;

  const real_number PI = acosl(-1);

  inline static real_number &eps() {
    static real_number EPS = 1e-10;
    return EPS;
  }

  static void set_eps(real_number EPS) {
    eps() = EPS;
  }

  inline int sign(real_number r) {
    set_eps(1e-10);
    if (r < -eps()) return -1;
    if (r > +eps()) return +1;
    return 0;
  }

  inline bool equals(real_number r1, real_number r2) {
    return sign(r1 - r2) == 0;
  }
}

// point
namespace geometry {
  using point = complex< real_number >;
  using points = vector< point >;

  istream &operator>>(istream &is, point &p) {
    real_number x, y;
    is >> x >> y;
    p = point(x, y);
    return is;
  }

  ostream &operator<<(ostream &os, const point &p) {
    return os << p.real() << " " << p.imag();
  }

  point operator*(const point &p, const real_number &k) {
    return point(p.real() * k, p.imag() * k);
  }

  point rotate(const real_number &theta, const point &p) {
    return point(cos(theta) * p.real() + sin(-theta) * p.imag(),
                 sin(theta) * p.real() + cos(-theta) * p.imag());
  }

  bool equals(const point &a, const point &b) {
    return equals(a.real(), b.real()) and equals(a.imag(), b.imag());
  }
}

namespace geometry {
  bool compare_x(const point &a, const point &b) {
    return !equals(a.real(), b.real()) ? a.real() < b.real() : a.imag() < b.imag();
  }

  bool compare_y(const point &a, const point &b) {
    return !equals(a.imag(), b.imag()) ? a.imag() < b.imag() : a.real() < b.real();
  }
}

// product
namespace geometry {
  real_number cross(const point &a, const point &b) {
    return a.real() * b.imag() - a.imag() * b.real();
  }

  real_number dot(const point &a, const point &b) {
    return a.real() * b.real() + a.imag() * b.imag();
  }
}

// ccw
namespace geometry {
  constexpr int COUNTER_CLOCKWISE = +1;
  constexpr int CLOCKWISE         = -1;
  constexpr int ONLINE_BACK       = +2; // c-a-b
  constexpr int ONLINE_FRONT      = -2; // a-b-c
  constexpr int ON_SEGMENT        =  0; // a-c-b
  int ccw(const point &a, point b, point c) {
    b = b - a, c = c - a;
    if (sign(cross(b, c)) == +1) return COUNTER_CLOCKWISE;
    if (sign(cross(b, c)) == -1) return CLOCKWISE;
    if (sign(dot(b, c)) == -1) return ONLINE_BACK;
    if (norm(b) < norm(c)) return ONLINE_FRONT;
    return ON_SEGMENT;
  }
}

// polygon
namespace geometry {
  using polygon = vector< point >;
  using polygons = vector< polygon >;
}

// area
namespace geometry {
  real_number area(const polygon &poly) {
    int n = poly.size();
    real_number res = 0;
    for (int i = 0; i < n; ++i) {
      res += cross(poly[i], poly[(i + 1) % n]);
    }
    return res / 2;
  }
}

using namespace geometry;

void solve() {
  int n = input();
  
  vector< pair<point, int> > pts;
  range(i, 0, n) {
    point p;
    cin >> p;
    pts.emplace_back(p, i + 1);
  }

  whole(sort, pts, [](auto &a, auto &b) { return compare_x(a.first, b.first); });

  auto udp = make_vector(n, n, n, n + 1, real_number(inf));
  auto uval = make_vector(n, n, n, n + 1, pair<int, int>(-1, -1));
  range(s, 0, n) range(t, s + 1, n) {
    udp[s][s][t][2] = 0;
  }

  range(s, 0, n) range(p, s, n) range(t, p + 1, n) range(k, 2, n) {
    point q = pts[s].first;

    point a = pts[p].first;
    point b = pts[t].first;

    if (udp[s][p][t][k] > inf - 1) continue;
    range(i, t + 1, n) {
      point c = pts[i].first;
      if (ccw(a, b, c) != CLOCKWISE) continue;
      polygon poly({q, b, c});
      real_number S = abs(area(poly));

      if (sign(udp[s][t][i][k + 1] - (udp[s][p][t][k] + S)) > 0) {
        udp[s][t][i][k + 1] = udp[s][p][t][k] + S;
        uval[s][t][i][k + 1] = make_pair(p, t);
      }
    }
  }

  auto ddp = make_vector(n, n, n, n + 1, real_number(inf));
  auto dval = make_vector(n, n, n, n + 1, pair<int, int>(-1, -1));
  range(s, 0, n) range(t, s + 1, n) {
    ddp[s][s][t][2] = 0;
  }

  range(s, 0, n) range(p, s, n) range(t, p + 1, n) range(k, 2, n) {
    point q = pts[s].first;
    
    point a = pts[p].first;
    point b = pts[t].first;

    if (ddp[s][p][t][k] > inf - 1) continue;
    range(i, t + 1, n) {
      point c = pts[i].first;
      if (ccw(a, b, c) != COUNTER_CLOCKWISE) continue;
      polygon poly({q, b, c});
      real_number S = abs(area(poly));

      if (sign(ddp[s][t][i][k + 1] - (ddp[s][p][t][k] + S)) > 0) {
        ddp[s][t][i][k + 1] = ddp[s][p][t][k] + S;
        dval[s][t][i][k + 1] = make_pair(p, t);
      }
    }
  }

  auto upre = make_vector(n, n, n + 1, -1);
  range(s, 0, n) range(t, s + 1, n) range(k, 2, n + 1) {
    int &idx = upre[s][t][k];
    range(p, s, t) {
      if (udp[s][p][t][k] > inf - 1) continue;
      if (idx == -1 or sign(udp[s][idx][t][k] - udp[s][p][t][k]) > 0) {
        idx = p;
      }
    }
  }

  auto dpre = make_vector(n, n, n + 1, -1);
  range(s, 0, n) range(t, s + 1, n) range(k, 2, n + 1) {
    int &idx = dpre[s][t][k];
    range(p, s, t) {
      if (ddp[s][p][t][k] > inf - 1) continue;
      if (idx == -1 or sign(ddp[s][idx][t][k] - ddp[s][p][t][k]) > 0) {
        idx = p;
      }
    }
  }

  int q = input();
  range(_, 0, q) {
    int k = input();

    real_number min_area = inf;
    int S = -1, T = -1, A = -1, P = -1, Q = -1;
    range(s, 0, n) range(t, s + 1, n) range(a, 2, k + 1) {
      int b = k + 2 - a;

      int p = upre[s][t][a];
      int q = dpre[s][t][b];

      if (p == -1 or q == -1) continue;

      real_number now_area = udp[s][p][t][a] + ddp[s][q][t][b];
      if (sign(min_area - now_area) <= 0) continue;
      min_area = now_area;
      S = s;
      T = t;
      A = a;
      P = p;
      Q = q;
    }

    if (S == -1) {
      cout << "NA" << endl;
      continue;
    }

    vector< int > idxs;
    {
      int p = Q, t = T, a = k + 2 - A;
      while (true) {
        idxs.emplace_back(t);
        if (p == S) break;
        tie(p, t) = dval[S][p][t][a];
        a--;
      }
    }

    whole(reverse, idxs);
    idxs.pop_back();

    {
      int p = P, t = T, a = A;
      while (true) {
        idxs.emplace_back(t);
        if (p == S) break;
        tie(p, t) = uval[S][p][t][a];
        a--;
      }
    }

    idxs.emplace_back(S);

    int st = 0;
    point pt = pts[idxs[0]].first;
    range(i, 1, idxs.size()) {
      point a = pts[idxs[i]].first;
      if (pt.imag() < a.imag()) continue;
      if (pt.imag() > a.imag()) {
        st = i;
        continue;
      }
      if (pt.real() > a.real()) {
        st = i;
      }
    }

    vector< int > ans;
    range(i, 0, idxs.size()) {
      ans.emplace_back(pts[idxs[(i + st) % idxs.size()]].second);
    }

    cout << ans << endl;
  }
}

signed main() {
  solve();
}
accuracy: 0.6666666666666666
time_ms: 20
memory_kb: 46628
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;

// template {{{
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;

#define  range(i, l, r) for (i64 i = (i64)(l); i < (i64)(r); (i) += 1)
#define rrange(i, l, r) for (i64 i = (i64)(r) - 1; i >= (i64)(l); (i) -= 1)

#define  whole(f, x, ...) ([&](decltype((x)) container) { return (f)(  begin(container),  end(container), ## __VA_ARGS__); })(x)
#define rwhole(f, x, ...) ([&](decltype((x)) container) { return (f)( rbegin(container), rend(container), ## __VA_ARGS__); })(x)

#define debug(x) cerr << "(" << __LINE__ << ")" << #x << ": " << (x) << endl

constexpr i32 inf   = 1001001001;
constexpr i64 infll = 1001001001001001001ll;

constexpr i32 dx[] = {0, -1, 1, 0, -1, 1, -1, 1}; 
constexpr i32 dy[] = {-1, 0, 0, 1, -1, -1, 1, 1};

struct IoSetup { IoSetup(i32 x = 15){ cin.tie(0); ios::sync_with_stdio(0); cout << fixed << setprecision(x); cerr << fixed << setprecision(x); } } iosetup;

template <typename T = i64> T input() { T x; cin >> x; return x; }

template <typename T> ostream &operator<<(ostream &os, vector<T> &v) { range(i, 0, v.size()) { os << v[i] << (i + 1 != (int)v.size() ? " " : ""); } return os; } 
template <typename T> istream &operator>>(istream &is, vector<T> &v) { for (T &in : v) is >> in; return is; }

template <typename T1, typename T2> ostream &operator<<(ostream &os, pair<T1, T2> p) { os << "(" << p.first << ", " << p.second << ")"; return os; }
template <typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &p) { is >> p.first >> p.second; return is; }

template <typename T> vector<T> make_vector(size_t a, T b) { return vector<T>(a, b); }
template <typename... Ts> auto make_vector(size_t a, Ts... ts) { return vector<decltype(make_vector(ts...))>(a, make_vector(ts...)); }

template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }
// }}}

// base
namespace geometry {
  using namespace std;
  using real_number = long double;

  const real_number PI = acosl(-1);

  inline static real_number &eps() {
    static real_number EPS = 1e-10;
    return EPS;
  }

  static void set_eps(real_number EPS) {
    eps() = EPS;
  }

  inline int sign(real_number r) {
    set_eps(1e-10);
    if (r < -eps()) return -1;
    if (r > +eps()) return +1;
    return 0;
  }

  inline bool equals(real_number r1, real_number r2) {
    return sign(r1 - r2) == 0;
  }
}

// point
namespace geometry {
  using point = complex< real_number >;
  using points = vector< point >;

  istream &operator>>(istream &is, point &p) {
    real_number x, y;
    is >> x >> y;
    p = point(x, y);
    return is;
  }

  ostream &operator<<(ostream &os, const point &p) {
    return os << p.real() << " " << p.imag();
  }

  point operator*(const point &p, const real_number &k) {
    return point(p.real() * k, p.imag() * k);
  }

  point rotate(const real_number &theta, const point &p) {
    return point(cos(theta) * p.real() + sin(-theta) * p.imag(),
                 sin(theta) * p.real() + cos(-theta) * p.imag());
  }

  bool equals(const point &a, const point &b) {
    return equals(a.real(), b.real()) and equals(a.imag(), b.imag());
  }
}

namespace geometry {
  bool compare_x(const point &a, const point &b) {
    return !equals(a.real(), b.real()) ? a.real() < b.real() : a.imag() < b.imag();
  }

  bool compare_y(const point &a, const point &b) {
    return !equals(a.imag(), b.imag()) ? a.imag() < b.imag() : a.real() < b.real();
  }
}

// product
namespace geometry {
  real_number cross(const point &a, const point &b) {
    return a.real() * b.imag() - a.imag() * b.real();
  }

  real_number dot(const point &a, const point &b) {
    return a.real() * b.real() + a.imag() * b.imag();
  }
}

// ccw
namespace geometry {
  constexpr int COUNTER_CLOCKWISE = +1;
  constexpr int CLOCKWISE         = -1;
  constexpr int ONLINE_BACK       = +2; // c-a-b
  constexpr int ONLINE_FRONT      = -2; // a-b-c
  constexpr int ON_SEGMENT        =  0; // a-c-b
  int ccw(const point &a, point b, point c) {
    b = b - a, c = c - a;
    if (sign(cross(b, c)) == +1) return COUNTER_CLOCKWISE;
    if (sign(cross(b, c)) == -1) return CLOCKWISE;
    if (sign(dot(b, c)) == -1) return ONLINE_BACK;
    if (norm(b) < norm(c)) return ONLINE_FRONT;
    return ON_SEGMENT;
  }
}

// polygon
namespace geometry {
  using polygon = vector< point >;
  using polygons = vector< polygon >;
}

// area
namespace geometry {
  real_number area(const polygon &poly) {
    int n = poly.size();
    real_number res = 0;
    for (int i = 0; i < n; ++i) {
      res += cross(poly[i], poly[(i + 1) % n]);
    }
    return res / 2;
  }
}

using namespace geometry;

void solve() {
  int n = input();
  
  vector< pair<point, int> > pts;
  range(i, 0, n) {
    point p;
    cin >> p;
    pts.emplace_back(p, i + 1);
  }

  whole(sort, pts, [](auto &a, auto &b) { return compare_x(a.first, b.first); });

  auto udp = make_vector(n, n, n, n + 1, real_number(infll));
  auto uval = make_vector(n, n, n, n + 1, pair<int, int>(-1, -1));
  range(s, 0, n) range(t, s + 1, n) {
    udp[s][s][t][2] = 0;
  }

  range(s, 0, n) range(p, s, n) range(t, p + 1, n) range(k, 2, n) {
    point q = pts[s].first;

    point a = pts[p].first;
    point b = pts[t].first;

    range(i, t + 1, n) {
      point c = pts[i].first;
      if (ccw(a, b, c) != CLOCKWISE) continue;
      polygon poly({q, b, c});
      real_number S = abs(area(poly));

      if (sign(udp[s][t][i][k + 1] - (udp[s][p][t][k] + S)) > 0) {
        udp[s][t][i][k + 1] = udp[s][p][t][k] + S;
        uval[s][t][i][k + 1] = make_pair(p, t);
      }
    }
  }

  auto ddp = make_vector(n, n, n, n + 1, real_number(infll));
  auto dval = make_vector(n, n, n, n + 1, pair<int, int>(-1, -1));
  range(s, 0, n) range(t, s + 1, n) {
    ddp[s][s][t][2] = 0;
  }

  range(s, 0, n) range(p, s, n) range(t, p + 1, n) range(k, 2, n) {
    point q = pts[s].first;
    
    point a = pts[p].first;
    point b = pts[t].first;

    range(i, t + 1, n) {
      point c = pts[i].first;
      if (ccw(a, b, c) != COUNTER_CLOCKWISE) continue;
      polygon poly({q, b, c});
      real_number S = abs(area(poly));

      if (sign(ddp[s][t][i][k + 1] - (ddp[s][p][t][k] + S)) > 0) {
        ddp[s][t][i][k + 1] = ddp[s][p][t][k] + S;
        dval[s][t][i][k + 1] = make_pair(p, t);
      }
    }
  }

  auto upre = make_vector(n, n, n + 1, -1);
  range(s, 0, n) range(t, s + 1, n) range(k, 2, n + 1) {
    int &idx = upre[s][t][k];
    range(p, s, t) {
      if (udp[s][p][t][k] > inf - 1) continue;
      if (idx == -1 or sign(udp[s][idx][t][k] - udp[s][p][t][k]) > 0) {
        idx = p;
      }
    }
  }

  auto dpre = make_vector(n, n, n + 1, -1);
  range(s, 0, n) range(t, s + 1, n) range(k, 2, n + 1) {
    int &idx = dpre[s][t][k];
    range(p, s, t) {
      if (ddp[s][p][t][k] > inf - 1) continue;
      if (idx == -1 or sign(ddp[s][idx][t][k] - ddp[s][p][t][k]) > 0) {
        idx = p;
      }
    }
  }

  int q = input();
  range(_, 0, q) {
    int k = input();

    real_number min_area = infll;
    int S = -1, T = -1, A = -1, P = -1, Q = -1;
    range(s, 0, n) range(t, s + 1, n) range(a, 2, k + 1) {
      int b = k + 2 - a;

      int p = upre[s][t][a];
      int q = dpre[s][t][b];

      if (p == -1 or q == -1) continue;

      real_number now_area = udp[s][p][t][a] + ddp[s][q][t][b];
      if (sign(min_area - now_area) <= 0) continue;
      min_area = now_area;
      S = s;
      T = t;
      A = a;
      P = p;
      Q = q;
    }

    if (S == -1) {
      cout << "NA" << endl;
      continue;
    }

    vector< int > idxs;
    {
      int p = Q, t = T, a = k + 2 - A;
      while (true) {
        idxs.emplace_back(t);
        if (p == S) break;
        tie(p, t) = dval[S][p][t][a];
        a--;
      }
    }

    whole(reverse, idxs);
    idxs.pop_back();

    {
      int p = P, t = T, a = A;
      while (true) {
        idxs.emplace_back(t);
        if (p == S) break;
        tie(p, t) = uval[S][p][t][a];
        a--;
      }
    }

    idxs.emplace_back(S);

    int st = 0;
    point pt = pts[idxs[0]].first;
    range(i, 1, idxs.size()) {
      point a = pts[idxs[i]].first;
      if (pt.imag() < a.imag()) continue;
      if (pt.imag() > a.imag()) {
        st = i;
        continue;
      }
      if (pt.real() > a.real()) {
        st = i;
      }
    }

    vector< int > ans;
    range(i, 0, idxs.size()) {
      ans.emplace_back(pts[idxs[(i + st) % idxs.size()]].second);
    }

    cout << ans << endl;
  }
}

signed main() {
  solve();
}
accuracy: 0.6666666666666666
time_ms: 70
memory_kb: 46620
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

// template {{{
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;

#define  range(i, l, r) for (i64 i = (i64)(l); i < (i64)(r); (i) += 1)
#define rrange(i, l, r) for (i64 i = (i64)(r) - 1; i >= (i64)(l); (i) -= 1)

#define  whole(f, x, ...) ([&](decltype((x)) container) { return (f)(  begin(container),  end(container), ## __VA_ARGS__); })(x)
#define rwhole(f, x, ...) ([&](decltype((x)) container) { return (f)( rbegin(container), rend(container), ## __VA_ARGS__); })(x)

#define debug(x) cerr << "(" << __LINE__ << ")" << #x << ": " << (x) << endl

constexpr i32 inf   = 1001001001;
constexpr i64 infll = 1001001001001001001ll;

constexpr i32 dx[] = {0, -1, 1, 0, -1, 1, -1, 1}; 
constexpr i32 dy[] = {-1, 0, 0, 1, -1, -1, 1, 1};

struct IoSetup { IoSetup(i32 x = 15){ cin.tie(0); ios::sync_with_stdio(0); cout << fixed << setprecision(x); cerr << fixed << setprecision(x); } } iosetup;

template <typename T = i64> T input() { T x; cin >> x; return x; }

template <typename T> ostream &operator<<(ostream &os, vector<T> &v) { range(i, 0, v.size()) { os << v[i] << (i + 1 != (int)v.size() ? " " : ""); } return os; } 
template <typename T> istream &operator>>(istream &is, vector<T> &v) { for (T &in : v) is >> in; return is; }

template <typename T1, typename T2> ostream &operator<<(ostream &os, pair<T1, T2> p) { os << "(" << p.first << ", " << p.second << ")"; return os; }
template <typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &p) { is >> p.first >> p.second; return is; }

template <typename T> vector<T> make_vector(size_t a, T b) { return vector<T>(a, b); }
template <typename... Ts> auto make_vector(size_t a, Ts... ts) { return vector<decltype(make_vector(ts...))>(a, make_vector(ts...)); }

template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }
// }}}

// base
namespace geometry {
  using namespace std;
  using real_number = long double;

  const real_number PI = acosl(-1);

  inline static real_number &eps() {
    static real_number EPS = 1e-10;
    return EPS;
  }

  static void set_eps(real_number EPS) {
    eps() = EPS;
  }

  inline int sign(real_number r) {
    set_eps(1e-10);
    if (r < -eps()) return -1;
    if (r > +eps()) return +1;
    return 0;
  }

  inline bool equals(real_number r1, real_number r2) {
    return sign(r1 - r2) == 0;
  }
}

// point
namespace geometry {
  using point = complex< real_number >;
  using points = vector< point >;

  istream &operator>>(istream &is, point &p) {
    real_number x, y;
    is >> x >> y;
    p = point(x, y);
    return is;
  }

  ostream &operator<<(ostream &os, const point &p) {
    return os << p.real() << " " << p.imag();
  }

  point operator*(const point &p, const real_number &k) {
    return point(p.real() * k, p.imag() * k);
  }

  point rotate(const real_number &theta, const point &p) {
    return point(cos(theta) * p.real() + sin(-theta) * p.imag(),
                 sin(theta) * p.real() + cos(-theta) * p.imag());
  }

  bool equals(const point &a, const point &b) {
    return equals(a.real(), b.real()) and equals(a.imag(), b.imag());
  }
}

namespace geometry {
  bool compare_x(const point &a, const point &b) {
    return !equals(a.real(), b.real()) ? a.real() < b.real() : a.imag() < b.imag();
  }

  bool compare_y(const point &a, const point &b) {
    return !equals(a.imag(), b.imag()) ? a.imag() < b.imag() : a.real() < b.real();
  }
}

// product
namespace geometry {
  real_number cross(const point &a, const point &b) {
    return a.real() * b.imag() - a.imag() * b.real();
  }

  real_number dot(const point &a, const point &b) {
    return a.real() * b.real() + a.imag() * b.imag();
  }
}

// ccw
namespace geometry {
  constexpr int COUNTER_CLOCKWISE = +1;
  constexpr int CLOCKWISE         = -1;
  constexpr int ONLINE_BACK       = +2; // c-a-b
  constexpr int ONLINE_FRONT      = -2; // a-b-c
  constexpr int ON_SEGMENT        =  0; // a-c-b
  int ccw(const point &a, point b, point c) {
    b = b - a, c = c - a;
    if (sign(cross(b, c)) == +1) return COUNTER_CLOCKWISE;
    if (sign(cross(b, c)) == -1) return CLOCKWISE;
    if (sign(dot(b, c)) == -1) return ONLINE_BACK;
    if (norm(b) < norm(c)) return ONLINE_FRONT;
    return ON_SEGMENT;
  }
}

// polygon
namespace geometry {
  using polygon = vector< point >;
  using polygons = vector< polygon >;
}

// area
namespace geometry {
  real_number area(const polygon &poly) {
    int n = poly.size();
    real_number res = 0;
    for (int i = 0; i < n; ++i) {
      res += cross(poly[i], poly[(i + 1) % n]);
    }
    return res / 2;
  }
}

using namespace geometry;

void solve() {
  int n = input();
  
  vector< pair<point, int> > pts;
  range(i, 0, n) {
    point p;
    cin >> p;
    pts.emplace_back(p, i + 1);
  }

  whole(sort, pts, [](auto &a, auto &b) { return compare_x(a.first, b.first); });

  auto udp = make_vector(n, n, n, n + 1, real_number(inf));
  auto uval = make_vector(n, n, n, n + 1, pair<int, int>(-1, -1));
  range(s, 0, n) range(t, s + 1, n) {
    udp[s][s][t][2] = 0;
  }

  range(s, 0, n) range(p, s, n) range(t, p + 1, n) range(k, 2, n) {
    point q = pts[s].first;

    point a = pts[p].first;
    point b = pts[t].first;

    range(i, t + 1, n) {
      point c = pts[i].first;
      if (ccw(a, b, c) != CLOCKWISE) continue;
      polygon poly({q, b, c});
      real_number S = abs(area(poly));

      if (sign(udp[s][t][i][k + 1] - (udp[s][p][t][k] + S)) > 0) {
        udp[s][t][i][k + 1] = udp[s][p][t][k] + S;
        uval[s][t][i][k + 1] = make_pair(p, t);
      }
    }
  }

  auto ddp = make_vector(n, n, n, n + 1, real_number(inf));
  auto dval = make_vector(n, n, n, n + 1, pair<int, int>(-1, -1));
  range(s, 0, n) range(t, s + 1, n) {
    ddp[s][s][t][2] = 0;
  }

  range(s, 0, n) range(p, s, n) range(t, p + 1, n) range(k, 2, n) {
    point q = pts[s].first;
    
    point a = pts[p].first;
    point b = pts[t].first;

    range(i, t + 1, n) {
      point c = pts[i].first;
      if (ccw(a, b, c) != COUNTER_CLOCKWISE) continue;
      polygon poly({q, b, c});
      real_number S = abs(area(poly));

      if (sign(ddp[s][t][i][k + 1] - (ddp[s][p][t][k] + S)) > 0) {
        ddp[s][t][i][k + 1] = ddp[s][p][t][k] + S;
        dval[s][t][i][k + 1] = make_pair(p, t);
      }
    }
  }

  auto upre = make_vector(n, n, n + 1, -1);
  range(s, 0, n) range(t, s + 1, n) range(k, 2, n + 1) {
    int &idx = upre[s][t][k];
    range(p, s, t) {
      if (udp[s][p][t][k] > inf - 1) continue;
      if (idx == -1 or sign(udp[s][idx][t][k] - udp[s][p][t][k]) > 0) {
        idx = p;
      }
    }
  }

  auto dpre = make_vector(n, n, n + 1, -1);
  range(s, 0, n) range(t, s + 1, n) range(k, 2, n + 1) {
    int &idx = dpre[s][t][k];
    range(p, s, t) {
      if (ddp[s][p][t][k] > inf - 1) continue;
      if (idx == -1 or sign(ddp[s][idx][t][k] - ddp[s][p][t][k]) > 0) {
        idx = p;
      }
    }
  }

  int q = input();
  range(_, 0, q) {
    int k = input();

    real_number min_area = inf;
    int S = -1, T = -1, A = -1, P = -1, Q = -1;
    range(s, 0, n) range(t, s + 1, n) range(a, 2, k + 1) {
      int b = k + 2 - a;

      int p = upre[s][t][a];
      int q = dpre[s][t][b];

      if (p == -1 or q == -1) continue;

      real_number now_area = udp[s][p][t][a] + ddp[s][q][t][b];
      if (sign(min_area - now_area) <= 0) continue;
      min_area = now_area;
      S = s;
      T = t;
      A = a;
      P = p;
      Q = q;
    }

    if (S == -1) {
      cout << "NA" << endl;
      continue;
    }

    vector< int > idxs;
    {
      int p = Q, t = T, a = k + 2 - A;
      while (true) {
        idxs.emplace_back(t);
        if (p == S) break;
        tie(p, t) = dval[S][p][t][a];
        a--;
      }
    }

    whole(reverse, idxs);
    idxs.pop_back();

    {
      int p = P, t = T, a = A;
      while (true) {
        idxs.emplace_back(t);
        if (p == S) break;
        tie(p, t) = uval[S][p][t][a];
        a--;
      }
    }

    idxs.emplace_back(S);

    int st = 0;
    point pt = pts[idxs[0]].first;
    range(i, 1, idxs.size()) {
      point a = pts[idxs[i]].first;
      if (pt.imag() < a.imag()) continue;
      if (pt.imag() > a.imag()) {
        st = i;
        continue;
      }
      if (pt.real() > a.real()) {
        st = i;
      }
    }

    vector< int > ans;
    range(i, 0, idxs.size()) {
      ans.emplace_back(pts[idxs[(i + st) % idxs.size()]].second);
    }

    cout << ans << endl;
  }
}

signed main() {
  solve();
}
accuracy: 0.6666666666666666
time_ms: 70
memory_kb: 46668
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

// template {{{
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;

#define  range(i, l, r) for (i64 i = (i64)(l); i < (i64)(r); (i) += 1)
#define rrange(i, l, r) for (i64 i = (i64)(r) - 1; i >= (i64)(l); (i) -= 1)

#define  whole(f, x, ...) ([&](decltype((x)) container) { return (f)(  begin(container),  end(container), ## __VA_ARGS__); })(x)
#define rwhole(f, x, ...) ([&](decltype((x)) container) { return (f)( rbegin(container), rend(container), ## __VA_ARGS__); })(x)

#define debug(x) cerr << "(" << __LINE__ << ")" << #x << ": " << (x) << endl

constexpr i32 inf   = 1001001001;
constexpr i64 infll = 1001001001001001001ll;

constexpr i32 dx[] = {0, -1, 1, 0, -1, 1, -1, 1}; 
constexpr i32 dy[] = {-1, 0, 0, 1, -1, -1, 1, 1};

struct IoSetup { IoSetup(i32 x = 15){ cin.tie(0); ios::sync_with_stdio(0); cout << fixed << setprecision(x); cerr << fixed << setprecision(x); } } iosetup;

template <typename T = i64> T input() { T x; cin >> x; return x; }

template <typename T> ostream &operator<<(ostream &os, vector<T> &v) { range(i, 0, v.size()) { os << v[i] << (i + 1 != (int)v.size() ? " " : ""); } return os; } 
template <typename T> istream &operator>>(istream &is, vector<T> &v) { for (T &in : v) is >> in; return is; }

template <typename T1, typename T2> ostream &operator<<(ostream &os, pair<T1, T2> p) { os << "(" << p.first << ", " << p.second << ")"; return os; }
template <typename T1, typename T2> istream &operator>>(istream &is, pair<T1, T2> &p) { is >> p.first >> p.second; return is; }

template <typename T> vector<T> make_vector(size_t a, T b) { return vector<T>(a, b); }
template <typename... Ts> auto make_vector(size_t a, Ts... ts) { return vector<decltype(make_vector(ts...))>(a, make_vector(ts...)); }

template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }
// }}}

// base
namespace geometry {
  using namespace std;
  using real_number = long double;

  const real_number PI = acosl(-1);

  inline static real_number &eps() {
    static real_number EPS = 1e-10;
    return EPS;
  }

  static void set_eps(real_number EPS) {
    eps() = EPS;
  }

  inline int sign(real_number r) {
    set_eps(1e-10);
    if (r < -eps()) return -1;
    if (r > +eps()) return +1;
    return 0;
  }

  inline bool equals(real_number r1, real_number r2) {
    return sign(r1 - r2) == 0;
  }
}

// point
namespace geometry {
  using point = complex< real_number >;
  using points = vector< point >;

  istream &operator>>(istream &is, point &p) {
    real_number x, y;
    is >> x >> y;
    p = point(x, y);
    return is;
  }

  ostream &operator<<(ostream &os, const point &p) {
    return os << p.real() << " " << p.imag();
  }

  point operator*(const point &p, const real_number &k) {
    return point(p.real() * k, p.imag() * k);
  }

  point rotate(const real_number &theta, const point &p) {
    return point(cos(theta) * p.real() + sin(-theta) * p.imag(),
                 sin(theta) * p.real() + cos(-theta) * p.imag());
  }

  bool equals(const point &a, const point &b) {
    return equals(a.real(), b.real()) and equals(a.imag(), b.imag());
  }
}

namespace geometry {
  bool compare_x(const point &a, const point &b) {
    return !equals(a.real(), b.real()) ? a.real() < b.real() : a.imag() < b.imag();
  }

  bool compare_y(const point &a, const point &b) {
    return !equals(a.imag(), b.imag()) ? a.imag() < b.imag() : a.real() < b.real();
  }
}

// product
namespace geometry {
  real_number cross(const point &a, const point &b) {
    return a.real() * b.imag() - a.imag() * b.real();
  }

  real_number dot(const point &a, const point &b) {
    return a.real() * b.real() + a.imag() * b.imag();
  }
}

// ccw
namespace geometry {
  constexpr int COUNTER_CLOCKWISE = +1;
  constexpr int CLOCKWISE         = -1;
  constexpr int ONLINE_BACK       = +2; // c-a-b
  constexpr int ONLINE_FRONT      = -2; // a-b-c
  constexpr int ON_SEGMENT        =  0; // a-c-b
  int ccw(const point &a, point b, point c) {
    b = b - a, c = c - a;
    if (sign(cross(b, c)) == +1) return COUNTER_CLOCKWISE;
    if (sign(cross(b, c)) == -1) return CLOCKWISE;
    if (sign(dot(b, c)) == -1) return ONLINE_BACK;
    if (norm(b) < norm(c)) return ONLINE_FRONT;
    return ON_SEGMENT;
  }
}

// polygon
namespace geometry {
  using polygon = vector< point >;
  using polygons = vector< polygon >;
}

// area
namespace geometry {
  real_number area(const polygon &poly) {
    int n = poly.size();
    real_number res = 0;
    for (int i = 0; i < n; ++i) {
      res += cross(poly[i], poly[(i + 1) % n]);
    }
    return res / 2;
  }
}

using namespace geometry;

void solve() {
  int n = input();
  
  vector< pair<point, int> > pts;
  range(i, 0, n) {
    point p;
    cin >> p;
    pts.emplace_back(p, i + 1);
  }

  whole(sort, pts, [](auto &a, auto &b) { return compare_x(a.first, b.first); });

  auto udp = make_vector(n, n, n, n + 1, real_number(inf));
  auto uval = make_vector(n, n, n, n + 1, pair<int, int>(-1, -1));
  range(s, 0, n) range(t, s + 1, n) {
    udp[s][s][t][2] = 0;
  }

  range(s, 0, n) range(p, s, n) range(t, p + 1, n) range(k, 2, n) {
    point q = pts[s].first;

    point a = pts[p].first;
    point b = pts[t].first;

    range(i, t + 1, n) {
      point c = pts[i].first;
      if (ccw(a, b, c) != CLOCKWISE) continue;
      polygon poly({q, b, c});
      real_number S = abs(area(poly));

      if (sign(udp[s][t][i][k + 1] - (udp[s][p][t][k] + S)) > 0) {
        udp[s][t][i][k + 1] = udp[s][p][t][k] + S;
        uval[s][t][i][k + 1] = make_pair(p, t);
      }
    }
  }

  auto ddp = make_vector(n, n, n, n + 1, real_number(inf));
  auto dval = make_vector(n, n, n, n + 1, pair<int, int>(-1, -1));
  range(s, 0, n) range(t, s + 1, n) {
    ddp[s][s][t][2] = 0;
  }

  range(s, 0, n) range(p, s, n) range(t, p + 1, n) range(k, 2, n) {
    point q = pts[s].first;
    
    point a = pts[p].first;
    point b = pts[t].first;

    range(i, t + 1, n) {
      point c = pts[i].first;
      if (ccw(a, b, c) != COUNTER_CLOCKWISE) continue;
      polygon poly({q, b, c});
      real_number S = abs(area(poly));

      if (sign(ddp[s][t][i][k + 1] - (ddp[s][p][t][k] + S)) > 0) {
        ddp[s][t][i][k + 1] = ddp[s][p][t][k] + S;
        dval[s][t][i][k + 1] = make_pair(p, t);
      }
    }
  }

  auto upre = make_vector(n, n, n + 1, -1);
  range(s, 0, n) range(t, s + 1, n) range(k, 2, n + 1) {
    int &idx = upre[s][t][k];
    range(p, s, t) {
      if (udp[s][p][t][k] > 1e8) continue;
      if (idx == -1 or sign(udp[s][idx][t][k] - udp[s][p][t][k]) > 0) {
        idx = p;
      }
    }
  }

  auto dpre = make_vector(n, n, n + 1, -1);
  range(s, 0, n) range(t, s + 1, n) range(k, 2, n + 1) {
    int &idx = dpre[s][t][k];
    range(p, s, t) {
      if (ddp[s][p][t][k] > 1e8) continue;
      if (idx == -1 or sign(ddp[s][idx][t][k] - ddp[s][p][t][k]) > 0) {
        idx = p;
      }
    }
  }

  int q = input();
  range(_, 0, q) {
    int k = input();

    real_number min_area = inf;
    int S = -1, T = -1, A = -1, P = -1, Q = -1;
    range(s, 0, n) range(t, s + 1, n) range(a, 2, k + 1) {
      int b = k + 2 - a;

      int p = upre[s][t][a];
      int q = dpre[s][t][b];

      if (p == -1 or q == -1) continue;

      real_number now_area = udp[s][p][t][a] + ddp[s][q][t][b];
      if (sign(min_area - now_area) <= 0) continue;
      min_area = now_area;
      S = s;
      T = t;
      A = a;
      P = p;
      Q = q;
    }

    if (S == -1) {
      cout << "NA" << endl;
      continue;
    }

    vector< int > idxs;
    {
      int p = Q, t = T, a = k + 2 - A;
      while (true) {
        idxs.emplace_back(t);
        if (p == S) break;
        tie(p, t) = dval[S][p][t][a];
        a--;
      }
    }

    whole(reverse, idxs);
    idxs.pop_back();

    {
      int p = P, t = T, a = A;
      while (true) {
        idxs.emplace_back(t);
        if (p == S) break;
        tie(p, t) = uval[S][p][t][a];
        a--;
      }
    }

    idxs.emplace_back(S);

    int st = 0;
    point pt = pts[idxs[0]].first;
    range(i, 1, idxs.size()) {
      point a = pts[idxs[i]].first;
      if (pt.imag() < a.imag()) continue;
      if (pt.imag() > a.imag()) {
        st = i;
        continue;
      }
      if (pt.real() > a.real()) {
        st = i;
      }
    }

    vector< int > ans;
    range(i, 0, idxs.size()) {
      ans.emplace_back(pts[idxs[(i + st) % idxs.size()]].second);
    }

    cout << ans << endl;
  }
}

signed main() {
  solve();
}
accuracy: 0.6666666666666666
time_ms: 70
memory_kb: 46668
final_rank: 19

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int N;
pair<int,int>p[40];
int f[40][40];
int dp[41][40][40];
bool ok[40][40][40];
int L[40],R[40];
vector<int>Lk[40],Rk[40];
int ans[41];
vector<int>vs[41];
main()
{
	cin>>N;
	for(int i=3;i<=N;i++)ans[i]=1e9;
	for(int i=0;i<N;i++)cin>>p[i].first>>p[i].second;
	for(int i=0;i<N;i++)for(int j=0;j<N;j++)for(int k=0;k<N;k++)
	{
		int ax=p[j].first-p[i].first;
		int ay=p[j].second-p[i].second;
		int bx=p[k].first-p[i].first;
		int by=p[k].second-p[i].second;
		ok[i][j][k]=ax*by-bx*ay>0;
	}
	for(int i=0;i<N;i++)for(int j=0;j<N;j++)
	{
		f[i][j]=(p[i].first-p[j].first)*(p[i].second+p[j].second);
	}
	for(int I=0;I<N;I++)for(int J=0;J<N;J++)if(p[I].first<p[J].first)
	{
		for(int k=0;k<N;k++)for(int i=0;i<N;i++)for(int j=0;j<N;j++)dp[k][i][j]=1e9;
		dp[0][I][J]=f[I][J];
		vector<int>can;
		for(int i=0;i<N;i++)
		{
			if(i!=I&&i!=J&&ok[I][i][J]&&p[I].first<=p[i].first&&p[i].first<=p[J].first)
			{
				dp[1][I][i]=f[I][i];
				can.push_back(i);
			}
		}
		for(int j:can)if(dp[1][I][j]<(int)1e9)
		{
			for(int l:can)
				if(ok[I][j][l]&&ok[j][l][J])dp[2][j][l]=min(dp[2][j][l],dp[1][I][j]+f[j][l]);
		}
		for(int k=2;k<N;k++)
		{
			bool nxt=false;
			for(int i:can)for(int j:can)if(dp[k][i][j]<(int)1e9)
			{
				for(int l:can)if(ok[i][j][l]&&ok[j][l][J])
				{
					dp[k+1][j][l]=min(dp[k+1][j][l],dp[k][i][j]+f[j][l]);
					nxt=true;
				}
			}
			if(!nxt)break;
		}
		for(int k=0;k<N;k++)
		{
			L[k]=1e9;
			Lk[k].clear();
		}
		L[0]=dp[0][I][J];
		for(int k=1;k<N;k++)
		{
			int u=-1,v;
			for(int i=0;i<N;i++)for(int j:can)
				if(ok[i][j][J]&&dp[k][i][j]<(int)1e9&&dp[k][i][j]+f[j][J]<L[k])
			{
				L[k]=dp[k][i][j]+f[j][J];
				v=i;
				u=j;
			}
			if(u<0)continue;
			vector<int>now;
			now.push_back(u);
			if(k>1)now.push_back(v);
			int nk=k-2;
			while(nk>0)
			{
				int w=-1;
				for(int i:can)if(ok[i][v][u]&&dp[nk+1][i][v]+f[v][u]==dp[nk+2][v][u])
				{
					w=i;
					break;
				}
				now.push_back(w);
				u=v;
				v=w;
				nk--;
			}
			Lk[k]=now;
		}
		for(int k=0;k<N;k++)for(int i=0;i<N;i++)for(int j=0;j<N;j++)dp[k][i][j]=1e9;
		dp[0][J][I]=f[J][I];
		can.clear();
		for(int i=0;i<N;i++)
		{
			if(i!=I&&i!=J&&ok[J][i][I]&&p[I].first<=p[i].first&&p[i].first<=p[J].first)
			{
				dp[1][J][i]=f[J][i];
				can.push_back(i);
			}
		}
		for(int j:can)if(dp[1][J][j]<(int)1e9)
		{
			for(int l:can)
				if(ok[J][j][l]&&ok[j][l][I])dp[2][j][l]=min(dp[2][j][l],dp[1][J][j]+f[j][l]);
		}
		for(int k=2;k<N;k++)
		{
			bool nxt=false;
			for(int i:can)for(int j:can)if(dp[k][i][j]<(int)1e9)
			{
				for(int l:can)if(ok[i][j][l]&&ok[j][l][I])
				{
					dp[k+1][j][l]=min(dp[k+1][j][l],dp[k][i][j]+f[j][l]);
					nxt=true;
				}
			}
			if(!nxt)break;
		}
		for(int k=0;k<N;k++)
		{
			R[k]=1e9;
			Rk[k].clear();
		}
		R[0]=dp[0][J][I];
		for(int k=1;k<N;k++)
		{
			int u=-1,v;
			for(int i=0;i<N;i++)for(int j:can)
				if(ok[i][j][I]&&dp[k][i][j]<(int)1e9&&dp[k][i][j]+f[j][I]<R[k])
			{
				R[k]=dp[k][i][j]+f[j][I];
				v=i;
				u=j;
			}
			if(u<0)continue;
			vector<int>now;
			now.push_back(u);
			if(k>1)now.push_back(v);
			int nk=k-2;
			while(nk>0)
			{
				int w=-1;
				for(int i:can)if(ok[i][v][u]&&dp[nk+1][i][v]+f[v][u]==dp[nk+2][v][u])
				{
					w=i;
					break;
				}
				now.push_back(w);
				u=v;
				v=w;
				nk--;
			}
			Rk[k]=now;
		}
		for(int k=0;k<N;k++)if(L[k]<(int)1e9)for(int l=0;l<N;l++)if(R[l]<(int)1e9&&k+l+2<=N)
		{
			if(ans[k+l+2]>L[k]+R[l])
			{
				ans[k+l+2]=L[k]+R[l];
				vector<int>now;
				now.push_back(I);
				for(int i=Lk[k].size();i--;)now.push_back(Lk[k][i]);
				now.push_back(J);
				for(int i=Rk[l].size();i--;)now.push_back(Rk[l][i]);
				vs[k+l+2]=now;
			}
		}
	}
	int Q;cin>>Q;
	for(;Q--;)
	{
		int k;cin>>k;
		if(ans[k]<(int)1e9)
		{
			int id=0;
			for(int i=1;i<k;i++)
				if(p[vs[k][i]].second<p[vs[k][id]].second
					||p[vs[k][i]].second==p[vs[k][id]].second
					&&p[vs[k][i]].first<p[vs[k][id]].first)id=i;
			for(int i=0;i<k;i++)cout<<vs[k][(i+id)%k]+1<<(i+1==k?"\n":" ");
		}
		else cout<<"NA"<<endl;
	}
}
accuracy: 1
time_ms: 80
memory_kb: 3500
final_rank: 2

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 45

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
		X = Y = 0;
		index = 0;
	}

	Point(){
		x = y = 0.0;
		X = Y = 0;
		index = 0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	/*bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}*/

	bool operator<(const Point &p) const{
		if(Y != p.Y){

			return Y < p.Y;
		}else{

			return X < p.X;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
	int X,Y,index;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

struct Info{
	Info(int arg_index,double arg_rad){
		index = arg_index;
		rad = arg_rad;
	}
	bool operator<(const struct Info &arg) const{

		return rad < arg.rad;
	}
	int index;
	double rad;
};


int N;
Point input[SIZE],P[SIZE];
double NUM = 20000;
double work[SIZE][SIZE][SIZE];
double min_S[SIZE];
int TMP[SIZE][SIZE][SIZE][SIZE];
int ans[SIZE][SIZE];



double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}


double calc_S(Polygon g){

	int N = g.size();
	double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}


double calc_rad(Point p){

	if(p.y == 0){

		if(p.x > 0){

			return 0;

		}else{ //p.x < 0

			return M_PI;
		}

	}else if(p.x == 0){

		if(p.y > 0){

			return M_PI/2.0;
		}else{


			return 3*M_PI/2.0;
		}

	}else{

		double base = atan(fabs(p.y)/fabs(p.x));

		if(p.x > 0){

			if(p.y > 0){

				return base;

			}else{ //p.y < 0

				return 2*M_PI-base;
			}

		}else{ //p.x < 0

			if(p.y > 0){

				return M_PI-base;

			}else{

				return base+M_PI;
			}
		}
	}
}
int main(){

	scanf("%d",&N);
	for(int i = 0; i < N; i++){

		scanf("%d %d",&input[i].X,&input[i].Y);
		input[i].x = input[i].X;
		input[i].y = input[i].Y;
		input[i].index = i;
		P[i] = input[i];
	}

	sort(P,P+N);

	//全体最小値
	for(int i = 0; i <= N; i++){

		min_S[i] = BIG_NUM;
	}

	vector<Info> info;

	for(int base = 0; base <= N-3; base++){

		for(int i = 3; i <= N; i++){
			for(int pre = 0; pre < N; pre++){
				for(int t = 0; t < N; t++){

					work[i][pre][t] = BIG_NUM;
				}
			}
		}
		info.clear();

		for(int i = base+1; i < N; i++){

			double tmp_rad;

			tmp_rad = calc_rad(P[i]-P[base]);

			info.push_back(Info(P[i].index,tmp_rad));
		}

		sort(info.begin(),info.end());

		//三角形の面積
		for(int i = 0; i < info.size()-1; i++){
			int head = info[i].index;
			for(int k = i+1; k < info.size(); k++){
				int tail = info[k].index;

				Polygon poly;
				poly.push_back(P[base]);
				poly.push_back(input[head]);
				poly.push_back(input[tail]);

				double tmp_S = calc_S(poly);

				work[3][head][tail] = tmp_S;
				TMP[3][head][tail][0] = P[base].index;
				TMP[3][head][tail][1] = head;
				TMP[3][head][tail][2] = tail;
			}
		}

		for(int num = 4; num <= N; num++){
			for(int i = 0; i < info.size()-2; i++){
				int pre = info[i].index;
				for(int k = i+1; k < info.size()-1; k++){
					int t = info[k].index;
					if(fabs(work[num-1][pre][t]-BIG_NUM) < EPS)continue;

					for(int a = k+1; a < info.size(); a++){
						int next = info[a].index;

						if(ccw(input[t],input[next],input[pre]) == COUNTER_CLOCKWISE){

							Polygon poly;
							poly.push_back(P[base]);
							poly.push_back(input[t]);
							poly.push_back(input[next]);

							double tmp_S = calc_S(poly);


							if(work[num][t][next] > work[num-1][pre][t]+tmp_S+EPS){

								work[num][t][next] = work[num-1][pre][t]+tmp_S;
								for(int b = 0; b < num-1; b++){

									TMP[num][t][next][b] = TMP[num-1][pre][t][b];
								}
								TMP[num][t][next][num-1] = next;
							}
						}
					}
				}

			}
		}

		//全体のdpテーブルと比較
		for(int num = 3; num <= N; num++){
			for(int pre = 0; pre < N; pre++){
				for(int t = 0; t < N; t++){
					if(fabs(work[num][pre][t]-BIG_NUM) < EPS)continue;

					if(min_S[num] > work[num][pre][t]+EPS){

						min_S[num] = work[num][pre][t];
						for(int a = 0; a < num; a++){

							ans[num][a] = TMP[num][pre][t][a];
						}
					}
				}
			}
		}
	}

	int num_query;
	scanf("%d",&num_query);

	int num_P;
	for(int loop = 0; loop < num_query; loop++){

		scanf("%d",&num_P);

		if(fabs(min_S[num_P]-BIG_NUM) < EPS){

			printf("NA\n");
			continue;
		}

		printf("%d",ans[num_P][0]+1);
		for(int i = 1; i < num_P; i++){

			printf(" %d",ans[num_P][i]+1);
		}
		printf("\n");
	}

	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 6768
final_rank: 1

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 45

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
		X = Y = 0;
		index = 0;
	}

	Point(){
		x = y = 0.0;
		X = Y = 0;
		index = 0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	/*bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}*/

	bool operator<(const Point &p) const{
		if(Y != p.Y){

			return Y < p.Y;
		}else{

			return X < p.X;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
	int X,Y,index;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

struct Info{
	Info(int arg_index,double arg_rad){
		index = arg_index;
		rad = arg_rad;
	}
	bool operator<(const struct Info &arg) const{

		return rad < arg.rad;
	}
	int index;
	double rad;
};


int N;
Point input[SIZE],P[SIZE];
double NUM = 20000;
double dp[SIZE][SIZE][SIZE];
double work[SIZE][SIZE][SIZE];
double min_S[SIZE];
int TMP[SIZE][SIZE][SIZE][SIZE];
int table[SIZE][SIZE][SIZE][SIZE];
int ans[SIZE][SIZE];



double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}


double calc_S(Polygon g){

	int N = g.size();
	double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}


double calc_rad(Point p){

	if(p.y == 0){

		if(p.x > 0){

			return 0;

		}else{ //p.x < 0

			return M_PI;
		}

	}else if(p.x == 0){

		if(p.y > 0){

			return M_PI/2.0;
		}else{


			return 3*M_PI/2.0;
		}

	}else{

		double base = atan(fabs(p.y)/fabs(p.x));

		if(p.x > 0){

			if(p.y > 0){

				return base;

			}else{ //p.y < 0

				return 2*M_PI-base;
			}

		}else{ //p.x < 0

			if(p.y > 0){

				return M_PI-base;

			}else{

				return base+M_PI;
			}
		}
	}
}
int main(){

	scanf("%d",&N);
	for(int i = 0; i < N; i++){

		scanf("%d %d",&input[i].X,&input[i].Y);
		input[i].x = input[i].X;
		input[i].y = input[i].Y;
		input[i].index = i;
		P[i] = input[i];
	}

	sort(P,P+N);

	for(int i = 0; i <= N; i++){
		for(int s = 0; s <= N; s++){
			for(int t = 0; t <= N; t++){

				dp[i][s][t] = BIG_NUM;
			}
		}
	}

	//全体最小値
	for(int i = 0; i <= N; i++){

		min_S[i] = BIG_NUM;
	}

	vector<Info> info;

	for(int base = 0; base <= N-3; base++){
	//for(int base = 6; base <= 6; base++){

		//P[base].debug();

		for(int i = 0; i <= N; i++){
			for(int s = 0; s <= N; s++){
				for(int t = 0; t <= N; t++){

					work[i][s][t] = BIG_NUM;
				}
			}
		}
		info.clear();

		for(int i = base+1; i < N; i++){

			double tmp_rad;

			tmp_rad = calc_rad(P[i]-P[base]);

			info.push_back(Info(P[i].index,tmp_rad));
		}

		sort(info.begin(),info.end());

		//三角形の面積
		for(int i = 0; i < info.size()-1; i++){
			int head = info[i].index;
			for(int k = i+1; k < info.size(); k++){
				int tail = info[k].index;

				Polygon poly;
				poly.push_back(P[base]);
				poly.push_back(input[head]);
				poly.push_back(input[tail]);

				double tmp_S = calc_S(poly);

				work[3][head][tail] = tmp_S;
				TMP[3][head][tail][0] = P[base].index;
				TMP[3][head][tail][1] = head;
				TMP[3][head][tail][2] = tail;
			}
		}

		for(int num = 4; num <= N; num++){
			for(int i = 0; i < info.size()-2; i++){
				int s = info[i].index;
				for(int k = i+1; k < info.size()-1; k++){
					int t = info[k].index;
					if(fabs(work[num-1][s][t]-BIG_NUM) < EPS)continue;

					for(int a = k+1; a < info.size(); a++){
						int next = info[a].index;

						int t_pre = TMP[num-1][s][t][num-3];

						if(ccw(input[t],input[next],input[t_pre]) == COUNTER_CLOCKWISE){

							Polygon poly;
							poly.push_back(P[base]);
							poly.push_back(input[t]);
							poly.push_back(input[next]);

							double tmp_S = calc_S(poly);


							if(work[num][s][next] > work[num-1][s][t]+tmp_S+EPS){
								work[num][s][next] = work[num-1][s][t]+tmp_S;
								for(int b = 0; b < num-1; b++){

									TMP[num][s][next][b] = TMP[num-1][s][t][b];
								}
								TMP[num][s][next][num-1] = next;
							}
						}
					}
				}
			}
		}

		//全体のdpテーブルと比較
		for(int num = 3; num <= N; num++){
			for(int s = 0; s < N; s++){
				for(int t = 0; t < N; t++){
					if(fabs(work[num][s][t]-BIG_NUM) < EPS)continue;

					if(min_S[num] > work[num][s][t]+EPS){

						min_S[num] = work[num][s][t];
						for(int a = 0; a < num; a++){


							ans[num][a] = TMP[num][s][t][a];
						}
					}
				}
			}
		}
	}

	int num_query;
	scanf("%d",&num_query);

	int num_P;
	for(int loop = 0; loop < num_query; loop++){

		scanf("%d",&num_P);

		if(fabs(min_S[num_P]-BIG_NUM) < EPS){

			printf("NA\n");
			continue;
		}

		//printf("min_S:%.3lf\n",min_S[num_P]);

		printf("%d",ans[num_P][0]+1);
		for(int i = 1; i < num_P; i++){

			printf(" %d",ans[num_P][i]+1);
		}
		printf("\n");
	}

	return 0;
}
accuracy: 0.7777777777777778
time_ms: 20
memory_kb: 7588
final_rank: 13

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 45

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
		X = Y = 0;
		index = 0;
	}

	Point(){
		x = y = 0.0;
		X = Y = 0;
		index = 0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	/*bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}*/

	bool operator<(const Point &p) const{
		if(Y != p.Y){

			return Y < p.Y;
		}else{

			return X < p.X;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}

	double x,y;
	int X,Y,index;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	/*void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}*/
	Point p[2];
};

struct Info{
	Info(int arg_index,double arg_rad){
		index = arg_index;
		rad = arg_rad;
	}
	bool operator<(const struct Info &arg) const{

		return rad < arg.rad;
	}
	int index;
	double rad;
};


int N;
Point input[SIZE],P[SIZE];
double NUM = 20000;
double dp[SIZE][SIZE][SIZE];
double work[SIZE][SIZE][SIZE];
double min_S[SIZE];
int TMP[SIZE][SIZE][SIZE][SIZE];
int table[SIZE][SIZE][SIZE][SIZE];
int ans[SIZE][SIZE];
bool check[SIZE];



double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}


double calc_S(Polygon g){

	int N = g.size();
	double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}


double calc_rad(Point p){

	if(p.y == 0){

		if(p.x > 0){

			return 0;

		}else{ //p.x < 0

			return M_PI;
		}

	}else if(p.x == 0){

		if(p.y > 0){

			return M_PI/2.0;
		}else{


			return 3*M_PI/2.0;
		}

	}else{

		double base = atan(fabs(p.y)/fabs(p.x));

		if(p.x > 0){

			if(p.y > 0){

				return base;

			}else{ //p.y < 0

				return 2*M_PI-base;
			}

		}else{ //p.x < 0

			if(p.y > 0){

				return M_PI-base;

			}else{

				return base+M_PI;
			}
		}
	}
}
int main(){

	scanf("%d",&N);
	for(int i = 0; i < N; i++){

		scanf("%d %d",&input[i].X,&input[i].Y);
		input[i].x = input[i].X;
		input[i].y = input[i].Y;
		input[i].index = i;
		P[i] = input[i];
	}

	sort(P,P+N);

	for(int i = 0; i <= N; i++){
		for(int s = 0; s <= N; s++){
			for(int t = 0; t <= N; t++){

				dp[i][s][t] = BIG_NUM;
			}
		}
	}

	//全体最小値
	for(int i = 0; i <= N; i++){

		min_S[i] = BIG_NUM;
	}

	vector<Info> info;

	for(int base = 0; base <= N-3; base++){

		//P[base].debug();

		for(int i = 0; i <= N; i++){
			for(int s = 0; s <= N; s++){
				for(int t = 0; t <= N; t++){

					work[i][s][t] = BIG_NUM;
				}
			}
		}
		info.clear();

		Point C = Point(P[base].x+NUM,P[base].y); //rad計算用

		for(int i = base+1; i < N; i++){

			double tmp_rad;

			tmp_rad = calc_rad(P[i]-P[base]);

			info.push_back(Info(P[i].index,tmp_rad));
		}

		sort(info.begin(),info.end());

		//三角形の面積
		for(int i = 0; i < info.size()-1; i++){
			int head = info[i].index;
			for(int k = i+1; k < info.size(); k++){
				int tail = info[k].index;

				Polygon poly;
				poly.push_back(P[base]);
				poly.push_back(input[head]);
				poly.push_back(input[tail]);

				double tmp_S = calc_S(poly);

				work[3][head][tail] = tmp_S;
				TMP[3][head][tail][0] = P[base].index;
				TMP[3][head][tail][1] = head;
				TMP[3][head][tail][2] = tail;
			}
		}

		for(int num = 4; num <= N; num++){
			for(int s = 0; s < N; s++){
				for(int t = 0; t < N; t++){

					if(fabs(work[num-1][s][t]-BIG_NUM) < EPS)continue;
					for(int a = 0; a < N; a++){

						check[a] = false;
					}
					for(int a = 0; a < num-1; a++){

						check[TMP[num-1][s][t][a]] = true;
					}
					for(int a = base+1; a < N; a++){
						int next = P[a].index;
						if(check[next])continue;

						int t_pre = TMP[num-1][s][t][num-3];

						if(ccw(input[t],input[next],input[t_pre]) == COUNTER_CLOCKWISE &&
								ccw(input[t],input[next],P[base]) == COUNTER_CLOCKWISE){

							Polygon poly;
							poly.push_back(P[base]);
							poly.push_back(input[t]);
							poly.push_back(input[next]);

							double tmp_S = calc_S(poly);

							if(work[num][s][next] > work[num-1][s][t]+tmp_S+EPS){
								work[num][s][next] = work[num-1][s][t]+tmp_S;
								for(int a = 0; a < num-1; a++){

									TMP[num][s][next][a] = TMP[num-1][s][t][a];
								}
								TMP[num][s][next][num-1] = next;
							}
						}
					}
				}
			}
		}

		//全体のdpテーブルと比較
		for(int num = 3; num <= N; num++){
			for(int s = 0; s < N; s++){
				for(int t = 0; t < N; t++){
					if(fabs(work[num][s][t]-BIG_NUM) < EPS)continue;

					if(min_S[num] > work[num][s][t]+EPS){

						min_S[num] = work[num][s][t];
						for(int a = 0; a < num; a++){

							ans[num][a] = TMP[num][s][t][a];
						}
					}
				}
			}
		}
	}

	int num_query;
	scanf("%d",&num_query);

	int num_P;
	for(int loop = 0; loop < num_query; loop++){

		scanf("%d",&num_P);

		if(fabs(min_S[num_P]-BIG_NUM) < EPS){

			printf("NA\n");
			continue;
		}

		//printf("min_S:%.3lf\n",min_S[num_P]);

		printf("%d",ans[num_P][0]+1);
		for(int i = 1; i < num_P; i++){

			printf(" %d",ans[num_P][i]+1);
		}
		printf("\n");
	}

	return 0;
}
accuracy: 0.7777777777777778
time_ms: 30
memory_kb: 7456
final_rank: 14

code_snippet: #include <iostream>
#include <cmath>
#include <tuple>
#include <vector>
#include <algorithm>
using namespace std;

struct Point {
	long long px, py;
};

bool operator<(const Point& a1, const Point& a2) {
	if (a1.px < a2.px) return true;
	if (a1.px > a2.px) return false;
	if (a1.py < a2.py) return true;
	return false;
}

Point operator-(const Point& a1, const Point& a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

bool ccw(Point a1, Point a2, Point a3) {
	Point v1 = a2 - a1;
	Point v2 = a3 - a1;
	long long eval = v1.px * v2.py - v1.py * v2.px;
	if (eval > 0) return true;
	return false;
}

// 入力
int N;
Point G[44];

// 前準備
double dist[44][44];
bool flag[44][44][44];

// 動的計画法
int pres1[44][44][44];
int pres2[44][44][44];
double dp1[44][44][44];
double dp2[44][44][44];

// 答え
double MinValue[44];
vector<int> Answer[44];

void init() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (i == j) dist[i][j] = 1e9;
			else {
				dist[i][j] = (G[i].px - G[j].px) * (G[i].py + G[j].py);
			}
		}
	}
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			for (int k = 0; k < N; k++) {
				if (i == j || j == k || k == i) continue;
				flag[i][j][k] = ccw(G[i], G[j], G[k]);
			}
		}
	}
}

vector<int> fukugen1(int v1, int v2, int v3) {
	vector<int> vec;
	int cx1 = v2, cx2 = v3;
	vec.push_back(cx2);
	vec.push_back(cx1);
	for (int u = v1; u >= 2; u--) {
		int nex = pres1[u][cx1][cx2];
		vec.push_back(nex);
		cx2 = cx1;
		cx1 = nex;
	}
	return vec;
}

vector<int> fukugen2(int v1, int v2, int v3) {
	vector<int> vec;
	int cx1 = v2, cx2 = v3;
	vec.push_back(cx2);
	vec.push_back(cx1);
	for (int u = v1; u >= 2; u--) {
		int nex = pres2[u][cx1][cx2];
		vec.push_back(nex);
		cx2 = cx1;
		cx1 = nex;
	}
	return vec;
}

void solve(int stt) {
	for (int t = 0; t <= N; t++) {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) dp1[t][i][j] = 1e9;
			for (int j = 0; j < N; j++) dp2[t][i][j] = 1e9;
		}
	}
	for (int i = 0; i < N; i++) { if (G[stt] < G[i]) dp1[1][stt][i] = dist[stt][i]; }
	for (int i = 0; i < N; i++) { if (G[stt] < G[i]) dp2[1][stt][i] = -dist[stt][i]; }
	
	// DP の遷移
	for (int t = 0; t < N; t++) {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (dp1[t][i][j] > 8e8) continue;
				for (int k = 0; k < N; k++) {
					if (flag[i][j][k] == false || !(G[j] < G[k])) continue;
					double cost = dp1[t][i][j] + dist[j][k];
					if (dp1[t + 1][j][k] > cost) {
						dp1[t + 1][j][k] = cost;
						pres1[t + 1][j][k] = i;
					}
				}
			}
		}
	}
	for (int t = 0; t < N; t++) {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (dp2[t][i][j] > 8e8) continue;
				for (int k = 0; k < N; k++) {
					if (flag[i][j][k] == true || !(G[j] < G[k])) continue;
					double cost = dp2[t][i][j] - dist[j][k];
					if (dp2[t + 1][j][k] > cost) {
						dp2[t + 1][j][k] = cost;
						pres2[t + 1][j][k] = i;
					}
				}
			}
		}
	}

	// DP の復元
	for (int t = 1; t <= N; t++) {
		for (int u = 1; u <= N - t; u++) {
			for (int i = 0; i < N; i++) {
				pair<double, int> cost1 = make_pair(1e9, -1);
				pair<double, int> cost2 = make_pair(1e9, -1);
				for (int k = 0; k < N; k++) cost1 = min(cost1, make_pair(dp1[t][k][i], k));
				for (int k = 0; k < N; k++) cost2 = min(cost2, make_pair(dp2[u][k][i], k));
				if (cost1.second == -1 || cost2.second == -1) continue;
				double TotalCost = cost1.first + cost2.first;
				if (MinValue[t + u] > TotalCost) {
					MinValue[t + u] = TotalCost;
					vector<int> v1 = fukugen1(t, cost1.second, i); reverse(v1.begin(), v1.end());
					vector<int> v2 = fukugen2(u, cost2.second, i); reverse(v2.begin(), v2.end());
					vector<int> v = v1;
					for (int j = (int)v2.size() - 2; j >= 1; j--) v.push_back(v2[j]);
					Answer[t + u] = v;
				}
			}
		}
	}
}

int main() {
	// 入力
	cin >> N;
	for (int i = 0; i < N; i++) cin >> G[i].px >> G[i].py;

	// 計算
	init();
	for (int i = 3; i <= N; i++) MinValue[i] = 1e9;
	for (int i = 0; i < N; i++) {
		solve(i);
	}

	// 出力
	int Q; cin >> Q;
	for (int i = 1; i <= Q; i++) {
		int K; cin >> K;
		if (MinValue[K] >= 8e8) cout << "NA" << endl;
		else {
			tuple<long long, long long, int> minp = make_tuple(1 << 30, 1 << 30, -1);
			for (int j = 0; j < Answer[K].size(); j++) {
				minp = min(minp, make_tuple(G[Answer[K][j]].py, G[Answer[K][j]].px, j));
			}
			for (int j = 0; j < Answer[K].size(); j++) {
				if (j) cout << " ";
				cout << Answer[K][(j + get<2>(minp)) % Answer[K].size()] + 1;
			}
			cout << endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 4876
final_rank: 3

code_snippet: #include <iostream>
#include <cmath>
#include <tuple>
#include <vector>
#include <algorithm>
using namespace std;

struct Point {
	long long px, py;
};

bool operator<(const Point& a1, const Point& a2) {
	if (a1.px < a2.px) return true;
	if (a1.px > a2.px) return false;
	if (a1.py < a2.py) return true;
	return false;
}

Point operator-(const Point& a1, const Point& a2) {
	return Point{ a1.px - a2.px, a1.py - a2.py };
}

bool ccw(Point a1, Point a2, Point a3) {
	Point v1 = a2 - a1;
	Point v2 = a3 - a1;
	long long eval = v1.px * v2.py - v1.py * v2.px;
	if (eval > 0) return true;
	return false;
}

// 入力
int N;
Point G[44];

// 前準備
double dist[44][44];
bool flag[44][44][44];

// 動的計画法
int pres1[44][44][44];
int pres2[44][44][44];
double dp1[44][44][44];
double dp2[44][44][44];

// 答え
double MinValue[44];
vector<int> Answer[44];

void init() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (i == j) dist[i][j] = 1e9;
			else {
				dist[i][j] = (G[i].px - G[j].px) * (G[i].py + G[j].py);
			}
		}
	}
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			for (int k = 0; k < N; k++) {
				if (i == j || j == k || k == i) continue;
				flag[i][j][k] = ccw(G[i], G[j], G[k]);
			}
		}
	}
}

vector<int> fukugen1(int v1, int v2, int v3) {
	vector<int> vec;
	int cx1 = v2, cx2 = v3;
	vec.push_back(cx2);
	vec.push_back(cx1);
	for (int u = v1; u >= 2; u--) {
		int nex = pres1[u][cx1][cx2];
		vec.push_back(nex);
		cx2 = cx1;
		cx1 = nex;
	}
	return vec;
}

vector<int> fukugen2(int v1, int v2, int v3) {
	vector<int> vec;
	int cx1 = v2, cx2 = v3;
	vec.push_back(cx2);
	vec.push_back(cx1);
	for (int u = v1; u >= 2; u--) {
		int nex = pres2[u][cx1][cx2];
		vec.push_back(nex);
		cx2 = cx1;
		cx1 = nex;
	}
	return vec;
}

void solve(int stt) {
	for (int t = 0; t <= N; t++) {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) dp1[t][i][j] = 1e9;
			for (int j = 0; j < N; j++) dp2[t][i][j] = 1e9;
		}
	}
	for (int i = 0; i < N; i++) { if (G[stt] < G[i]) dp1[1][stt][i] = dist[stt][i]; }
	for (int i = 0; i < N; i++) { if (G[stt] < G[i]) dp2[1][stt][i] = -dist[stt][i]; }
	
	// DP の遷移
	for (int t = 0; t < N; t++) {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (dp1[t][i][j] > 8e8) continue;
				for (int k = 0; k < N; k++) {
					if (flag[i][j][k] == false || !(G[j] < G[k])) continue;
					double cost = dp1[t][i][j] + dist[j][k];
					if (dp1[t + 1][j][k] > cost) {
						dp1[t + 1][j][k] = cost;
						pres1[t + 1][j][k] = i;
					}
				}
			}
		}
	}
	for (int t = 0; t < N; t++) {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (dp2[t][i][j] > 8e8) continue;
				for (int k = 0; k < N; k++) {
					if (flag[i][j][k] == true || !(G[j] < G[k])) continue;
					double cost = dp2[t][i][j] - dist[j][k];
					if (dp2[t + 1][j][k] > cost) {
						dp2[t + 1][j][k] = cost;
						pres2[t + 1][j][k] = i;
					}
				}
			}
		}
	}

	// DP の復元
	for (int t = 1; t <= N; t++) {
		for (int u = 1; u <= N - t; u++) {
			for (int i = 0; i < N; i++) {
				pair<double, int> cost1 = make_pair(1e9, -1);
				pair<double, int> cost2 = make_pair(1e9, -1);
				for (int k = 0; k < N; k++) cost1 = min(cost1, make_pair(dp1[t][k][i], k));
				for (int k = 0; k < N; k++) cost2 = min(cost2, make_pair(dp2[u][k][i], k));
				double TotalCost = cost1.first + cost2.first;
				if (MinValue[t + u] > TotalCost) {
					MinValue[t + u] = TotalCost;
					vector<int> v1 = fukugen1(t, cost1.second, i); reverse(v1.begin(), v1.end());
					vector<int> v2 = fukugen2(u, cost2.second, i); reverse(v2.begin(), v2.end());
					vector<int> v = v1;
					for (int j = (int)v2.size() - 2; j >= 1; j--) v.push_back(v2[j]);
					Answer[t + u] = v;
				}
			}
		}
	}
}

int main() {
	// 入力
	cin >> N;
	for (int i = 0; i < N; i++) cin >> G[i].px >> G[i].py;

	// 計算
	init();
	for (int i = 3; i <= N; i++) MinValue[i] = 1e9;
	for (int i = 0; i < N; i++) {
		solve(i);
	}

	// 出力
	int Q; cin >> Q;
	for (int i = 1; i <= Q; i++) {
		int K; cin >> K;
		if (MinValue[K] >= 8e8) cout << "NA" << endl;
		else {
			tuple<long long, long long, int> minp = make_tuple(1 << 30, 1 << 30, -1);
			for (int j = 0; j < Answer[K].size(); j++) {
				minp = min(minp, make_tuple(G[Answer[K][j]].py, G[Answer[K][j]].px, j));
			}
			for (int j = 0; j < Answer[K].size(); j++) {
				if (j) cout << " ";
				cout << Answer[K][(j + get<2>(minp)) % Answer[K].size()] + 1;
			}
			cout << endl;
		}
	}
	return 0;
}
accuracy: 0.6666666666666666
time_ms: 20
memory_kb: 4448
final_rank: 16

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

using real = int;
struct Point {
    real x, y;
    Point& operator+=(const Point a) { x += a.x; y += a.y;  return *this; }
    Point& operator-=(const Point a) { x -= a.x; y -= a.y;  return *this; }
    Point& operator*=(const real k) { x *= k; y *= k;  return *this; }
    Point& operator/=(const real k) { x /= k; y /= k;  return *this; }
    Point operator+(const Point a) const {return Point(*this) += a; }
    Point operator-(const Point a) const {return Point(*this) -= a; }
    Point operator*(const real k) const {return Point(*this) *= k; }
    Point operator/(const real k) const {return Point(*this) /= k; }
    bool operator<(const Point &a) const { return (x != a.x ? x < a.x : y < a.y); }
    explicit Point(real a = 0, real b = 0) : x(a), y(b) {};
};

istream& operator>> (istream& s, Point& P){
    s >> P.x >> P.y;
    return s;
}




template <class T, class U>
vector<T> make_v(U size, const T& init){ return vector<T>(static_cast<size_t>(size), init); }

template<class... Ts, class U>
auto make_v(U size, Ts... rest) { return vector<decltype(make_v(rest...))>(static_cast<size_t>(size), make_v(rest...)); }

template<class T> void chmin(T &a, const T &b){ a = (a < b ? a : b); }
template<class T> void chmax(T &a, const T &b){ a = (a > b ? a : b); }




int dp[41][40][40][40], prv[41][40][40][40];

int main() {
    int n;
    cin >> n;
    vector<Point> v(n);
    for (int i = 0; i < n; ++i) {
        cin >> v[i];
    }
    auto area = [](Point a, Point b, Point c){ return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); };
    auto to = make_v(n, n, vector<int>());
    fill_n((int*)dp, 41*40*40*40, INF<int>);
    fill_n((int*)prv, 41*40*40*40, 0);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if(i == j) continue;
            if(v[i].y <= v[j].y) dp[2][i][i][j] = 0;
            for (int k = 0; k < n; ++k) {
                if(i == k || j == k) continue;
                if(area(v[i], v[j], v[k]) > 0 && (v[i].y <= v[j].y || v[j].y >= v[k].y)){
                    to[i][j].emplace_back(k);
                }
            }
        }
    }
    for (int i = 2; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                for (int l = 0; l < n; ++l) {
                    if(dp[i][j][k][l] == INF<int>) continue;
                    for (auto &&m : to[k][l]) {
                        if(v[j].y > v[m].y || j == m) continue;
                        int a = area(v[j], v[l], v[m]);

                        if(a > 0 && dp[i+1][j][l][m] > dp[i][j][k][l]+a){
                            dp[i+1][j][l][m] = dp[i][j][k][l]+a;
                            prv[i+1][j][l][m] = k;
                        }
                    }
                }
            }
        }
    }
    vector<vector<int>> anss(n+1);
    for (int i = 3; i <= n; ++i) {
        int val = INF<int>, a = 0, b = 0, c = 0;
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                for (int l = 0; l < n; ++l) {
                    if(dp[i][j][k][l] < val){
                        val = dp[i][j][k][l];
                        a = j; b = k; c = l;
                    }
                }
            }
        }
        if(val == INF<int>) {
            continue;
        }
        vector<int> ans{c, b};
        for (int j = i; j >= 3; --j) {
            int x = prv[j][a][b][c];
            ans.emplace_back(x);
            c = b; b = x;
        }
        reverse(ans.begin(),ans.end());
        if(v[ans.front()].y == v[ans.back()].y){
            rotate(ans.begin(), ans.end()-1, ans.end());
        }
        anss[i] = ans;
    }
    int q;
    cin >> q;
    while(q--){
        int x;
        cin >> x;
        if(anss[x].empty()) puts("NA");
        else{
            for (int i = 0; i < anss[x].size(); ++i) {
                printf(i ? " %d" : "%d", anss[x][i]+1);
            }
            puts("");
        }
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 23784
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;

using i64 = int64_t;

const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);

using Point = complex<double>;
using Polygon = vector<Point>;

inline int sgn(const double &a) { return (a < -EPS ? -1 : (a > EPS ? 1 : 0)); }

inline bool eq(const Point &a, const Point &b) { return abs(a - b) < EPS; }

namespace std {
inline bool operator<(const Point &a, const Point &b) {
    if (sgn(a.imag() - b.imag()))
        return sgn(a.imag() - b.imag()) < 0;
    return sgn(a.real() - b.real()) < 0;
}
} // namespace std

double dot(const Point &a, const Point &b) { return real(conj(a) * b); }

double det(const Point &a, const Point &b) { return imag(conj(a) * b); }

struct Line {
    Point p1, p2;

    Line(Point p1 = Point(), Point p2 = Point()) : p1(p1), p2(p2) {}

    bool operator<(const Line &rhs) const {
        if (eq(p2, rhs.p2))
            return p1 < rhs.p1;
        return p2 < rhs.p2;
    }
    bool operator==(const Line &rhs) const {
        return (eq(p1, rhs.p1) && eq(p2, rhs.p2)) ||
               (eq(p1, rhs.p2) && eq(p2, rhs.p1));
    }
};

inline Point curr(const Polygon &p, const int &i) { return p[i % p.size()]; }

inline Point next(const Polygon &p, const int &i) {
    return p[(i + 1) % p.size()];
}

inline Point prev(const Polygon &p, const int &i) {
    return p[(i + p.size() - 1) % p.size()];
}

enum CCW {
    ONLINE_FRONT = -2,
    CLOCKWISE,
    ON_SEGMENT,
    COUNTER_CLOCKWISE,
    ONLINE_BACK
};

int ccw(Point p0, Point p1, Point p2) {
    Point a = p1 - p0;
    Point b = p2 - p0;
    if (sgn(det(a, b)) == 1)
        return COUNTER_CLOCKWISE;
    if (sgn(det(a, b)) == -1)
        return CLOCKWISE;
    if (sgn(dot(a, b)) == -1)
        return ONLINE_BACK;
    if (sgn(norm(b) - norm(a)) == 1)
        return ONLINE_FRONT;
    return ON_SEGMENT;
}

double dp[42][42][42][42]={0};
int prev_point[42][42][42][42]={0};
bool exists[42]={0};

int main(){
    int n;
    cin >> n;
    vector<pair<Point, int>> v;
    for(int i=0;i<n;++i){
        double x, y;
        cin >> x >> y;
        v.emplace_back(Point(x, y), i+1);
    }
    sort(v.begin(), v.end());
    vector<vector<int>> points_idx;
    for(int i=0;i<n;++i){
        points_idx.push_back(vector<int>());
        for(int j=i+1;j<n;++j){
            points_idx[i].push_back(j);
        }
        Point p = v[i].first;
        auto cmp = [p, v](int a, int b){
            double rad_a = atan2(v[a].first.imag() - p.imag(), v[a].first.real() - p.real());
            double rad_b = atan2(v[b].first.imag() - p.imag(), v[b].first.real() - p.real());
            return sgn(rad_a - rad_b) < 0;
        };
        sort(points_idx[i].begin(), points_idx[i].end(), cmp);
    }

    for(int i=0;i<n;++i){
        for(int j=3;j<=n;++j){
            for(int k=0;k<=n;++k){
                for(int l=0;l<=n;++l){
                    dp[i][j][k][l] = INF;
                }
            }
        }
    }

    for(int i=0;i<n;++i){
        for(int j=0;j<n;++j){
            for(int k=0;k<n;++k){
                if(ccw(v[i].first, v[j].first, v[k].first) != COUNTER_CLOCKWISE)continue;
                prev_point[i][3][j][k] = i;
                dp[i][3][j][k] = abs(det(v[j].first-v[i].first, v[k].first-v[i].first))/2.0;
            }
        }
    }
    exists[3] = true;

    for(int i=0;i<n;++i){
        for(int j=3;j<n;++j){
            for(int k=0;k<(int)points_idx[i].size()-2;++k){
                for(int l=k+1;l<(int)points_idx[i].size()-1;++l){
                    for(int m=l+1;m<(int)points_idx[i].size();++m){
                        Point a = v[points_idx[i][k]].first, b = v[points_idx[i][l]].first, c = v[points_idx[i][m]].first;
                        if(ccw(a, b, c) != COUNTER_CLOCKWISE)continue;
                        int k_idx = points_idx[i][k], l_idx = points_idx[i][l], m_idx = points_idx[i][m];
                        double tri_area = abs(det(c-v[i].first, b-v[i].first))/2.0;
                        double new_area = dp[i][j][k_idx][l_idx] + tri_area;
                        if(sgn(dp[i][j+1][l_idx][m_idx] - new_area) > 0){
                            dp[i][j+1][l_idx][m_idx] = new_area;
                            prev_point[i][j+1][l_idx][m_idx] = k_idx;
                            exists[j+1] = true;
                        }
                    }
                }
            }
        }
    }

    vector<vector<int>> ans(n+1);
    for(int i=3;i<=n;++i){
        double mini = INF;
        int sp = 0, ep1 = 0, ep2 = 0;
        for(int j=0;j<n;++j){
            for(int k=0;k<n;++k){
                for(int l=0;l<n;++l){
                    if(sgn(mini-dp[j][i][k][l]) > 0){
                        mini = dp[j][i][k][l];
                        sp = j;
                        ep1 = k;
                        ep2 = l;
                    }
                }
            }
        }
        vector<int> vp;
        vp.push_back(v[ep2].second); vp.push_back(v[ep1].second);
        int a = ep2, b = ep1, remain = i;
        while(b != sp){
            int c = prev_point[sp][remain][b][a];
            a = b;
            b = c;
            remain--;
            vp.push_back(v[c].second);
        }
        reverse(vp.begin(), vp.end());
        ans[i] = vp;
    }

    int q;
    cin >> q;
    for(int i=0;i<q;++i){
        int k;
        cin >> k;
        if(!exists[k])cout << "NA";
        else {
                for(int j=0;j<(int)ans[k].size();++j){
                if(j!=0)cout << " ";
                cout << ans[k][j];
            }
        }
        cout << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 26540
final_rank: 7

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
#include <utility>
using namespace std;
#define REP(i, n) for(int i=0; i<(n); i++)
const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};

namespace std{
    bool operator < (const P& a, const P& b){
        return (a.Y!=b.Y) ? a.Y<b.Y : a.X<b.X;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}

struct info{
    int sp, prev, curr;
    info(int s, int p, int c):sp(s),prev(p),curr(c){}
    info(){}
    bool operator < (const info &a) const{
        return (sp!=a.sp)? sp<a.sp: (prev!=a.prev)? prev<a.prev: curr<a.curr;
    }
};
double dp[40][40][40][41];
pair<int,int> prevtable[40][40][40][41];

int main(){
    int n;
    cin >> n;
    vector<pair<P, int> > ord(n);
    for(int i=0; i<n; i++){
        double x,y;
        cin >> x >> y;
        ord[i] = make_pair(P(x, y), i);
    }
    sort(ord.begin(), ord.end());

    VP p(n);
    vector<int> conv(n);
    for(int i=0; i<n; i++){
        p[i] = ord[i].first;
        conv[i] = ord[i].second +1;
    }

    int q;
    cin >> q;
    vector<int> query(q);
    for(int i=0; i<q; i++){
        cin >> query[i];
    }

    //dp[始点][前の点][今の点][点の数] = 最小面積 
    REP(i,n) REP(j,n) REP(k,n) REP(l,n+1) dp[i][j][k][l] = INF;
    set<info> next;
    for(int fp=0; fp<n; fp++){
        for(int sp=fp+1; sp<n; sp++){
            dp[fp][fp][sp][2] = 0;
            next.insert(info(fp, fp, sp));
        }
    } 

    for(int i=2; i<n; i++){
        set<info> newnext;
        for(info w: next){
            for(int j=w.sp+1; j<n; j++){
                int ret1 = ccw(p[w.prev], p[w.curr], p[j]);
                int ret2 = ccw(p[w.curr], p[j], p[w.sp]);
                if((ret1==1 || ret1==-2) && ret2!=-1){
                    double &update = dp[w.sp][w.curr][j][i+1];
                    double &now = dp[w.sp][w.prev][w.curr][i];
                    double area = cross(p[w.curr]-p[w.sp], p[j]-p[w.sp])/2;
                    if(now +area < update){
                        update = now +area;
                        newnext.insert(info(w.sp, w.curr, j));
                        prevtable[w.sp][w.curr][j][i+1] = make_pair(w.prev, w.curr);
                    }
                }
            }
        }
        next = newnext;
    }

    //経路復元
    for(int i=0; i<q; i++){
        vector<int> ans;
        int sp=-1, curr=-1, prev=-1;
        double minarea = INF;
        for(int s=0; s<n; s++){
            for(int p=0; p<n; p++){
                for(int c=0; c<n; c++){
                    if(dp[s][p][c][query[i]] < minarea){
                        minarea = dp[s][p][c][query[i]];
                        sp = s;
                        prev = p;
                        curr = c;
                    }
                }
            }
        }
        if(sp==-1){
            cout << "NA" << endl;
            continue;
        }
        ans.push_back(conv[curr]);
        ans.push_back(conv[prev]);
        for(int j=query[i]; j>2; j--){
            pair<int,int> pc = prevtable[sp][prev][curr][j];
            prev = pc.first;
            curr = pc.second;
            ans.push_back(conv[prev]);
        }
        for(int j=ans.size()-1; j>0; j--){
            cout << ans[j] << " ";
        }
        cout << ans[0] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 32248
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using LL = long long;
using VL = vector<LL>;
using VVL = vector<VL>;
using PLL = pair<LL, LL>;
using VS = vector<string>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

#define FF first
#define SS second

#define DUMP(x) cout<<#x<<":"<<(x)<<endl
template<class S, class T>
istream& operator>>(istream& is, pair<S,T>& p){
  return is >> p.FF >> p.SS;
}
template<class T>
istream& operator>>(istream& is, vector<T>& xs){
  for(auto& x: xs)
	is >> x;
  return is;
}
template<class S, class T>
ostream& operator<<(ostream& os, const pair<S,T>& p){
  return os << p.FF << " " << p.SS;
}
template<class T>
ostream& operator<<(ostream& os, const vector<T>& xs){
  for(unsigned int i=0;i<xs.size();++i)
	os << (i?" ":"") << xs[i];
  return os;
}
template<class T>
void maxi(T& x, T y){
  if(x < y) x = y;
}
template<class T>
void mini(T& x, T y){
  if(x > y) x = y;
}


const double EPS = 1e-6;
const double PI  = acos(-1.0);
const LL MOD = 1e9+7;
const double INF = 1e15;

class Point{
public:
  double x, y;

  Point(double x = 0.0, double y = 0.0) : x(x), y(y){}

  Point& operator += (const Point& p){ x += p.x; y += p.y; return *this;}
  Point operator + (const Point& p) const{ Point q = *this;return q += p;}
  Point& operator -= (const Point& p){ x -= p.x; y -= p.y; return *this;}
  Point operator - (const Point& p) const{ Point q = *this; return q -= p;}
  Point& operator *= (double a){ x *= a; y *= a; return *this;}
  Point operator * (double a) const{ Point q = *this; return q *= a;}
  Point& operator /= (double a){ x /= a; y /= a; return *this;}
  Point operator / (double a) const{ Point q = *this; return q /= a;}

  double abs() const { return sqrt(norm()); }
  double norm() const { return x*x + y*y; }
  Point& normalize(){ return *this /= abs(); }
  
  bool operator < (const Point &p) const{
	return y != p.y ? y < p.y : x < p.x;
  }
  
  //EPSは十分小さな値
  bool operator == (const Point &p) const {
	return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;
  }
  friend ostream& operator <<(ostream& os, const Point& p);
};
ostream& operator <<(ostream& os, const Point& p){
  return os << "(" << p.x << ","<<p.y << ")";
}

typedef vector<Point> Polygon;
typedef Point Vector;
//内積
double dot(Vector a, Vector b){
	return a.x*b.x + a.y*b.y;
}

//外積の大きさ
double cross(Vector a, Vector b){
	return a.x*b.y - a.y*b.x;
}

int ccw(Point p0, Point p1, Point p2){

	//p0->p1をp0始点、p1終点の基準ベクトルとしたとき

	//p0->p2が反時計回りになるとき
	static const int COUNTER_CLOCKWISE = 1;
	//p0->p2が時計回りになるとき
	static const int CLOCKWISE = -1;
	//p2,p0,p1の順で同一直線上にあるとき
	static const int ONLINE_BACK = 2;
	//p0,p1,p2 の順で同一直線上にある場合
	static const int ONLINE_FRONT = -2;
	//p2 が線分 p0p1 上にある場合
	static const int ON_SEGMENT = 0;

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if (cross(a, b) > EPS) return COUNTER_CLOCKWISE;
	if (cross(a, b) < -EPS) return CLOCKWISE;
	if (dot(a, b) < -EPS) return ONLINE_BACK;
	if (a.norm() < b.norm()) return ONLINE_FRONT;

	return ON_SEGMENT;
}
Polygon andrewScan(Polygon s){
	Polygon u, l;

	if (s.size() < 3) return s;

	sort(s.begin(), s.end()); //x,yを基準にソート

	u.push_back(s[0]);
	u.push_back(s[1]);

	l.push_back(s[s.size() - 1]);
	l.push_back(s[s.size() - 2]);

	//凸方の上部を生成
	for (unsigned int i = 2; i < s.size(); i++){
		for (int n = u.size(); n >= 2 && ccw(u[n - 2], u[n - 1], s[i]) == 1; n--){
			u.pop_back();
		}
		u.push_back(s[i]);
	}

	//凸法の下部を生成
	for (int i = s.size() - 3; i >= 0; i--){
		for (int n = l.size(); n >= 2 && ccw(l[n - 2], l[n - 1], s[i]) == 1; n--){
			l.pop_back();
		}
		l.push_back(s[i]);
	}

	//反時計回りになるように凸包の点の列
	reverse(l.begin(), l.end());
	for (int i = u.size() - 2; i >= 1; i--)
		l.push_back(u[i]);

	return l;
}

double tri_area(Point p1, Point p2, Point p3){
  return abs(cross(p2-p1, p3-p1)) / 2.;
}

double dp[41][41][41][41];
int rev[41][41][41][41];

int main(){
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int N;
  cin >> N;
  vector<pair<Point,int>> ps(N);
  REP(i,N){
	cin >> ps[i].FF.x >> ps[i].FF.y;
	ps[i].SS = i+1;
  }
  SORT(ps);

  fill((double*)dp, (double*)dp+41*41*41*41, INF);
  REP(i1,N) REP(i2,N) REP(i3,N){
	if(i1==i2 || i2 == i3 || i1==i3) continue;
	if(ps[i2] < ps[i1] || ps[i3] < ps[i1]) continue;
	if(ccw(ps[i1].FF, ps[i2].FF, ps[i3].FF) == 1){
	  dp[3][i1][i2][i3] = tri_area(ps[i1].FF, ps[i2].FF, ps[i3].FF);
	}
  }

  FOR(i,3,N) REP(b,N) REP(j,N) REP(k,N){
	if(dp[i][b][j][k] >= INF) continue;
	FOR(n,b+1,N){
	  if(n == b || n == j || n == k) continue;
	  if(ccw(ps[j].FF, ps[k].FF, ps[n].FF) != 1 || ccw(ps[b].FF, ps[n].FF, ps[k].FF) != -1) continue;
	  double res = dp[i][b][j][k] + tri_area(ps[k].FF, ps[n].FF, ps[b].FF);
	  if(res < dp[i+1][b][k][n]){
		dp[i+1][b][k][n] = res;
		rev[i+1][b][k][n] = j;
	  }
	}
  }

  int Q;
  cin >> Q;
  REP(q,Q){
	int K;
	cin >> K;

	int ab=-1, aj, ak;
	double best = INF;
	REP(b,N) REP(j,N) REP(k,N){
	  if(dp[K][b][j][k] >= INF) continue;
	  if(dp[K][b][j][k] <= best-EPS){
		best = dp[K][b][j][k];
		ab = b;
		aj = j;
		ak = k;
	  }
	  else if(abs(dp[K][b][j][k] - best) <= EPS){
		if(ps[b] < ps[ab]){
		  best = dp[K][b][j][k];
		  ab = b;
		  aj = j;
		  ak = k;
		}
	  }
	}
	if(ab == -1){
	  cout << "NA" << endl;
	  continue;
	}

	VI ans;
	for(int k=K;k>3;--k){
	  ans.PB(ps[ak].SS);
	  int r = rev[k][ab][aj][ak];
	  ak = aj;
	  aj = r;
	}
	ans.PB(ps[ak].SS);
	ans.PB(ps[aj].SS);
	ans.PB(ps[ab].SS);
	reverse(ALL(ans));
	cout << ans << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 26824
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using LL = long long;
using VL = vector<LL>;
using VVL = vector<VL>;
using PLL = pair<LL, LL>;
using VS = vector<string>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

#define FF first
#define SS second

#define DUMP(x) cout<<#x<<":"<<(x)<<endl
template<class S, class T>
istream& operator>>(istream& is, pair<S,T>& p){
  return is >> p.FF >> p.SS;
}
template<class T>
istream& operator>>(istream& is, vector<T>& xs){
  for(auto& x: xs)
	is >> x;
  return is;
}
template<class S, class T>
ostream& operator<<(ostream& os, const pair<S,T>& p){
  return os << p.FF << " " << p.SS;
}
template<class T>
ostream& operator<<(ostream& os, const vector<T>& xs){
  for(unsigned int i=0;i<xs.size();++i)
	os << (i?" ":"") << xs[i];
  return os;
}
template<class T>
void maxi(T& x, T y){
  if(x < y) x = y;
}
template<class T>
void mini(T& x, T y){
  if(x > y) x = y;
}


const double EPS = 1e-10;
const double PI  = acos(-1.0);
const LL MOD = 1e9+7;


class Point{
public:
  double x, y;

  Point(double x = 0.0, double y = 0.0) : x(x), y(y){}

  Point& operator += (const Point& p){ x += p.x; y += p.y; return *this;}
  Point operator + (const Point& p) const{ Point q = *this;return q += p;}
  Point& operator -= (const Point& p){ x -= p.x; y -= p.y; return *this;}
  Point operator - (const Point& p) const{ Point q = *this; return q -= p;}
  Point& operator *= (double a){ x *= a; y *= a; return *this;}
  Point operator * (double a) const{ Point q = *this; return q *= a;}
  Point& operator /= (double a){ x /= a; y /= a; return *this;}
  Point operator / (double a) const{ Point q = *this; return q /= a;}

  double abs() const { return sqrt(norm()); }
  double norm() const { return x*x + y*y; }
  Point& normalize(){ return *this /= abs(); }
  
  bool operator < (const Point &p) const{
	return y != p.y ? y < p.y : x < p.x;
  }
  
  //EPSは十分小さな値
  bool operator == (const Point &p) const {
	return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;
  }
  friend ostream& operator <<(ostream& os, const Point& p);
};
ostream& operator <<(ostream& os, const Point& p){
  return os << "(" << p.x << ","<<p.y << ")";
}

class Segment{
public:
  Point p1, p2;
  Segment(){}
  Segment(const Point& p1_, const Point& p2_)
	: p1(p1_), p2(p2_)
  {}
};

class Circle{
public:
	Point c;
	double r;
};

typedef vector<Point> Polygon;

//点を線として扱う
typedef Point Vector;
//線分を直線として扱う
typedef Segment Line;

//内積
double dot(Vector a, Vector b){
	return a.x*b.x + a.y*b.y;
}

//外積の大きさ
double cross(Vector a, Vector b){
	return a.x*b.y - a.y*b.x;
}

int ccw(Point p0, Point p1, Point p2){

	//p0->p1をp0始点、p1終点の基準ベクトルとしたとき

	//p0->p2が反時計回りになるとき
	static const int COUNTER_CLOCKWISE = 1;
	//p0->p2が時計回りになるとき
	static const int CLOCKWISE = -1;
	//p2,p0,p1の順で同一直線上にあるとき
	static const int ONLINE_BACK = 2;
	//p0,p1,p2 の順で同一直線上にある場合
	static const int ONLINE_FRONT = -2;
	//p2 が線分 p0p1 上にある場合
	static const int ON_SEGMENT = 0;

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if (cross(a, b) > EPS) return COUNTER_CLOCKWISE;
	if (cross(a, b) < -EPS) return CLOCKWISE;
	if (dot(a, b) < -EPS) return ONLINE_BACK;
	if (a.norm() < b.norm()) return ONLINE_FRONT;

	return ON_SEGMENT;
}
Polygon andrewScan(Polygon s){
	Polygon u, l;

	if (s.size() < 3) return s;

	sort(s.begin(), s.end()); //x,yを基準にソート

	u.push_back(s[0]);
	u.push_back(s[1]);

	l.push_back(s[s.size() - 1]);
	l.push_back(s[s.size() - 2]);

	//凸方の上部を生成
	for (int i = 2; i < s.size(); i++){
		for (int n = u.size(); n >= 2 && ccw(u[n - 2], u[n - 1], s[i]) == 1; n--){
			u.pop_back();
		}
		u.push_back(s[i]);
	}

	//凸法の下部を生成
	for (int i = s.size() - 3; i >= 0; i--){
		for (int n = l.size(); n >= 2 && ccw(l[n - 2], l[n - 1], s[i]) == 1; n--){
			l.pop_back();
		}
		l.push_back(s[i]);
	}

	//反時計回りになるように凸包の点の列
	reverse(l.begin(), l.end());
	for (int i = u.size() - 2; i >= 1; i--)
		l.push_back(u[i]);

	return l;
}

//多角形の面積を求める //凸包のソート済みが前提
double polygon_area(const Polygon& t){
  double ans=0.0;
  for(unsigned int i=0;i<t.size();i++)
	ans+=cross(t[i] , t[(i+1)%t.size()]);
  return ans/2;
}

vector<vector<Polygon>> pols(41);
vector<Polygon> ans(41);
VVI ansi(41);

int main(){
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int N;
  cin >> N;

  Polygon ps(N);
  REP(i,N) cin >> ps[i].x >> ps[i].y;

  REP(i1,N) REP(i2,i1) REP(i3,i2){
	Polygon p;
	p.push_back(ps[i1]);
	p.push_back(ps[i2]);
	p.push_back(ps[i3]);
	p = andrewScan(p);
	pols[3].EB(p);
  }

  FOR(i,3,N){
	//cout<<SZ(pols[i]) << endl;
	if(pols[i].empty()) break;

	double area = 1e15;
	while(!pols[i].empty()){
	  auto p = pols[i].back();
	  pols[i].pop_back();

	  double a = polygon_area(p);
	  if(a < area){
		area = a;
		ans[i] = p;
	  }

	  double poi = 1e15;
	  Polygon pyon;
	  REP(j,N){
		p.push_back(ps[j]);
		Polygon tmp = andrewScan(p);
		if(SZ(tmp) == i+1){
		  double poipoi = polygon_area(tmp);
		  if(poipoi < poi){
			poi = poipoi;
			pyon = tmp;
		  }
		}
		p.pop_back();
	  }
	  if(!pyon.empty())
		pols[i+1].EB(pyon);
	}
  }

  if(!pols[N].empty()){
	int i = N;
	int mi = 0;
	double area = polygon_area(pols[i][0]);
	FOR(j,1,SZ(pols[i])){
	  double a = polygon_area(pols[i][j]);
	  if(a < area){
		mi = j;
		area = a;
	  }
	}
	ans[i] = pols[i][mi];
  }

  FOR(i,3,N+1){
	if(ans[i].empty()) continue;
	for(auto& p: ans[i]){
	  REP(j,N){
		if(p == ps[j]){
		  ansi[i].PB(j+1);
		  break;
		}
	  }
	}
  }

  int Q;
  cin >> Q;
  REP(q,Q){
	int k;
	cin >> k;
	if(ansi[k].empty())
	  cout << "NA" << endl;
	else
	  cout << ansi[k] << endl;
  }

  return 0;
}
accuracy: 0.7777777777777778
time_ms: 750
memory_kb: 5188
final_rank: 15