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>
using namespace std;
long long gcd(long long a, long long b) {
  if (b > a) {
    return gcd(b, a);
  }
  if (b == 0) {
    return a;
  }
  return gcd(b, a % b);
}
long long expo(long long a, long long b, long long m) {
  long long res = 1;
  while (b > 0) {
    if (b & 1) res = (res * a) % m;
    a = (a * a) % m;
    b = b >> 1;
  }
  return res;
}
void extendgcd(long long a, long long b, long long *v) {
  if (b == 0) {
    v[0] = 1;
    v[1] = 0;
    v[2] = a;
    return;
  }
  extendgcd(b, a % b, v);
  long long x = v[1];
  v[1] = v[0] - v[1] * (a / b);
  v[0] = x;
  return;
}
long long mminv(long long a, long long b) {
  long long arr[3];
  extendgcd(a, b, arr);
  return arr[0];
}
long long mminvprime(long long a, long long b) { return expo(a, b - 2, b); }
void swap(long long &x, long long &y) {
  long long temp = x;
  x = y;
  y = temp;
}
long long combination(long long n, long long r, long long m, long long *fact,
                      long long *ifact) {
  long long val1 = fact[n];
  long long val2 = ifact[n - r];
  long long val3 = ifact[r];
  return (((val1 * val2) % m) * val3) % m;
}
void google(long long t) { cout << "Case #" << t << ": "; }
vector<long long> sieve(long long n) {
  long long *arr = new long long[n + 1]();
  vector<long long> vect;
  for (long long i = 2; i <= n; i++)
    if (arr[i] == 0) {
      vect.push_back(i);
      for (long long j = 2 * i; j <= n; j += i) arr[j] = 1;
    }
  return vect;
}
long long mod_add(long long a, long long b, long long m) {
  a = a % m;
  b = b % m;
  return (((a + b) % m) + m) % m;
}
long long mod_mul(long long a, long long b, long long m) {
  a = a % m;
  b = b % m;
  return (((a * b) % m) + m) % m;
}
long long mod_sub(long long a, long long b, long long m) {
  a = a % m;
  b = b % m;
  return (((a - b) % m) + m) % m;
}
long long mod_div(long long a, long long b, long long m) {
  a = a % m;
  b = b % m;
  return (mod_mul(a, mminvprime(b, m), m) + m) % m;
}
long long phin(long long n) {
  long long number = n;
  if (n % 2 == 0) {
    number /= 2;
    while (n % 2 == 0) n /= 2;
  }
  for (long long i = 3; i <= sqrt(n); i += 2) {
    if (n % i == 0) {
      while (n % i == 0) n /= i;
      number = (number / i * (i - 1));
    }
  }
  if (n > 1) number = (number / n * (n - 1));
  return number;
}
void c_p_c() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
}
set<pair<long long, long long> > pairs;
set<long long> s;
long long d[2001];
long long d2[2001];
long long cnt[2002];
void query2(long long num, long long n) {
  cout << "? " << num << "\n";
  cout.flush();
  for (long long i = 1; i <= n; i++) cin >> d2[i];
  s.erase(num);
  for (long long i = 1; i <= n; i++) {
    if (d2[i] == 1 && s.find(i) != s.end())
      pairs.insert(make_pair(min(num, i), max(num, i)));
  }
}
void query(long long num, long long n) {
  cout << "? " << num << "\n";
  cout.flush();
  for (long long i = 1; i <= n; i++) cin >> d[i];
  s.erase(num);
  memset(cnt, 0, sizeof(cnt));
  for (long long i = 1; i <= n; i++) {
    if (d[i] == 1) {
      pairs.insert(make_pair(min(num, i), max(num, i)));
    }
    if (s.find(i) != s.end()) cnt[d[i]]++;
  }
  long long maxv = 0;
  long long idx = 0;
  for (long long i = 1; i < n; i++) {
    if (cnt[i + 1] > maxv) {
      maxv = cnt[i - 1] + cnt[i + 1];
      idx = i;
    }
  }
  if (idx == 0) return;
  for (long long i = 1; i <= n; i++) {
    if (d[i] == idx && s.find(i) != s.end()) query2(i, n);
  }
}
int32_t main() {
  c_p_c();
  long long n;
  cin >> n;
  for (long long i = 1; i <= n; i++) s.insert(i);
  while (pairs.size() < n - 1) {
    long long bk = *s.begin();
    query(bk, n);
  }
  cout << "!" << endl;
  for (pair<long long, long long> p : pairs)
    cout << p.first << " " << p.second << endl;
}
