5
5 3
2 4
3 1
4 5
 4
2 4
3 2
2 1
 5
5 3
2 4
3 1
4 5
 2
1 2
 4
3 4
2 3
3 1
 10
8 10
2 9
7 8
4 1
7 3
4 7
2 5
2 4
4 6
 5
3 4
3 2
3 1
1 5
 3
1 2
2 3
 5
1 2
1 3
1 4
1 5

1 2
2 3
2 4
 1 3
2 4
3 5
4 5
 1 2
 1 3
2 3
3 4
 1 4
2 4
2 5
2 9
3 7
4 6
4 7
7 8
8 10
 1 3
1 5
2 3
3 4
 1 2
2 3
 1 2
1 3
1 4
1 5

#include <bits/stdc++.h>
#pragma GCC target("sse4.2")
using namespace std;
int dr[] = {0, 1, -1, 0, 1, -1, 1, -1};
int dc[] = {1, 0, 0, -1, 1, -1, -1, 1};
int drr[] = {-2, -1, 0, 1, 2};
int dcc[] = {-2, -1, 0, 1, 2};
bool chk(int a, int b, int n, int m) {
  return 0 <= a && a < n && 0 <= b && b < m;
}
long long exp(long long n, long long m, long long md) {
  long long a = 1;
  while (m > 0) {
    if (m & 1) a = (a * n % md) % md;
    m /= 2;
    n = (n * n) % md;
  }
  return a % md;
}
long long expm(long long n, long long m) {
  long long a = 1;
  while (m > 0) {
    if (a < 0 or a >= (1e18 + n - 1) / n) {
      return -1;
    }
    if (m & 1) a = (a * n);
    m /= 2;
    n = (n * n);
  }
  return a;
}
void disp(vector<int> v) {
  for (auto u : v) cout << u << " ";
  cout << endl;
}
void disp(vector<long long> v) {
  for (auto u : v) cout << u << " ";
  cout << endl;
}
struct custom_hash {
  static uint64_t splitmix64(uint64_t x) {
    x += 0x9e3779b97f4a7c15;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
    x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
    return x ^ (x >> 31);
  }
  size_t operator()(uint64_t x) const {
    static const uint64_t FIXED_RANDOM =
        chrono::steady_clock::now().time_since_epoch().count();
    return splitmix64(x + FIXED_RANDOM);
  }
};
auto random_address = [] {
  char *p = new char;
  delete p;
  return uint64_t(p);
};
const uint64_t SEED = chrono::steady_clock::now().time_since_epoch().count() *
                      (random_address() | 1);
mt19937_64 rng(SEED);
const int N = 2021;
int n;
int d[N], d0[N];
int vis[N];
vector<int> a, b;
set<pair<int, int>> s;
void go() {
  s.clear();
  cin >> n;
  for (long long i = 0; i < n; i++) {
    vis[i] = 0;
  }
  int q = 0;
  for (long long i = 0; i < n; i++) {
    if (vis[i]) continue;
    q++;
    if (q > (n + 1) / 2) {
      assert(2 > 3);
    }
    vis[i] = 1;
    cout << '?' << " " << i + 1 << endl;
    vector<int> o, e;
    for (long long j = 0; j < n; j++) {
      cin >> d[j];
      if (d[j] == 1) {
        o.push_back(j);
        s.insert(make_pair(min(j + 1, i + 1), max(j + 1, i + 1)));
        vis[j] = 1;
      } else if (d[j] == 2) {
        e.push_back(j);
      }
    }
    if (o.size() == 1) {
      for (int u : e) {
        vis[u] = 1;
        s.insert(make_pair(min(o[0] + 1, u + 1), max(o[0] + 1, u + 1)));
      }
    }
  }
  cout << '!' << endl;
  for (auto u : s) {
    cout << u.first << " " << u.second << endl;
  }
  fflush(stdout);
  exit(0);
}
int main() {
  cout << fixed << setprecision(11);
  cerr << fixed << setprecision(10);
  long long tt = 1;
  long long t = tt;
  auto start = std::chrono::high_resolution_clock::now();
  while (tt--) {
    go();
  }
  auto stop = std::chrono::high_resolution_clock::now();
  auto duration =
      std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start);
  cerr << "Time taken : "
       << ((long double)duration.count()) / ((long double)1e9) << "s " << endl;
}
