// // Created by yamunaku on 2020/12/03. // #include //#include using namespace std; //using namespace atcoder; #define rep(i, n) for(int i = 0; i < (n); i++) #define repl(i, l, r) for(int i = (l); i < (r); i++) #define per(i, n) for(int i = ((n)-1); i >= 0; i--) #define perl(i, l, r) for(int i = ((r)-1); i >= (l); i--) #define all(x) (x).begin(),(x).end() #define MOD9 998244353 #define MOD1 1000000007 #define IINF 1000000000 #define LINF 1000000000000000000 #define SP <<" "<< #define CYES cout<<"Yes"<; using mti = vector>; using vl = vector; using mtl = vector>; using pi = pair; using pl = pair; template using heap = priority_queue, function>; pair query(int i, int j) { cout << "?" SP i + 1 SP j + 1 << endl; int p, q; cin >> p >> q; return {p, q}; } int main() { //CFS; int n; cin >> n; map, vector> mp; repl(i, 1, n * n - n) { auto p = query(i, 0); mp[p].push_back(i); } int pi = -1, pj = -1; rep(i, n - 1) { rep(j, n) { map, int> sz; rep(k, n - 1) { rep(l, n) { if (i != k || j != l) { int p = k - i, q = l - j; if (p > q) swap(p, q); sz[{p, q}]++; } } } auto itr = sz.begin(); auto itr2 = mp.begin(); for (; itr != sz.end(); itr++, itr2++) { if (itr2->first != itr->first || itr2->second.size() != itr->second) goto next; } pi = i, pj = j; next:; } } mti ans(n - 1, vi(n, -1)); ans[pi][pj] = 0; auto pl = mp.begin()->first; if (pl.first != pl.second && (pi != 0 || pj != 0)) { int l = mp.begin()->second[0]; for (auto &c : mp) { int nx = pi + c.first.first, ny = pj + c.first.second; if (c.second.size() == 1) { if (nx < 0 || n - 1 <= nx || ny < 0 || n <= ny) { nx = pi + c.first.second, ny = pj + c.first.first; } ans[nx][ny] = c.second[0]; } else { auto s = query(c.second[0], l); if (nx == s.first && ny == s.second || nx == s.second && ny == s.first) { ans[nx][ny] = c.second[0]; ans[pi + c.first.second][pj + c.first.first] = c.second[1]; } else { ans[nx][ny] = c.second[1]; ans[pi + c.first.second][pj + c.first.first] = c.second[0]; } } } } else { int r = mp.rbegin()->second[0]; for (auto &c : mp) { int nx = pi + c.first.first, ny = pj + c.first.second; if (c.second.size() == 1) { if (nx < 0 || n - 1 <= nx || ny < 0 || n <= ny) { nx = pi + c.first.second, ny = pj + c.first.first; } ans[nx][ny] = c.second[0]; } else { auto s = query(c.second[0], r); if (nx == s.first + n - 2 && ny == s.second + n - 1 || nx == s.second + n - 2 && ny == s.first + n - 1) { ans[nx][ny] = c.second[0]; ans[pi + c.first.second][pj + c.first.first] = c.second[1]; } else { ans[nx][ny] = c.second[1]; ans[pi + c.first.second][pj + c.first.first] = c.second[0]; } } } } // rep(i, n - 1) { // rep(j, n) { // cout << ans[i][j] << " "; // } // cout << endl; // } vi ansp(n * n - n); rep(i, n - 1) rep(j, n) ansp[ans[i][j]] = i * n + j + n; cout << "!"; for (auto &x : ansp) cout << " " << x; cout << endl; return 0; }