#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <numbers>
#include <numeric>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <bit>
#include <deque>
#include <climits>
using namespace std;
using ll = long long;
using db = double;


/* 
void dfs(int v, int p) {
    for (auto u : g[v]) {
        dfs(u, v);
    }
}
*/


/*
int l = 0, r = n + 1;
while (r - l > 1) {
    int mid = (l + r) / 2;
    if (...) {
        l = mid;
    } else {
        r = mid;
    }
}
*/


struct SparseTable {
    vector<vector<ll>> t;

    SparseTable(int n, vector<ll> &a) : t(21, vector<ll>(a.size())) {
        for (int k = 0; k < 21; k++) {
            for (int r = 0; r < n; r++) {
                if (k == 0) {
                    t[k][r] = a[r];
                    continue;
                }

                t[k][r] = max(t[k - 1][r], t[k - 1][r - (1 << (k - 1))]);
            }
        }
    }

    /* ll get(int l, int r) {
        return max(t[][r],
                   t[][r]);
    } */
};


struct Node {
    int val;

    Node() : val(0) {}

    Node(int val) : val(val) {}

    Node merge(const Node &other) const {
        return Node(val + other.val);
    }
};


template <typename Node>
struct Segtree {
    vector<Node> t;
    const Node NE;

    Segtree(int n, const Node &NE) : NE(NE) {
        t.resize(4 * n + 10);
    }

    void build(int v, int l, int r, vector<Node> &a) {
        if (l + 1 == r) {
            t[v] = a[l];
            return;
        }

        int mid = (l + r) / 2;
        build(2 * v + 1, l, mid, a);
        build(2 * v + 2, mid, r, a);
        t[v] = t[2 * v + 1]
        .merge(t[2 * v + 2]);
    }

    Node get(int v, int l, int r, int lq, int rq) {
        if (r <= lq || rq <= l) {
            return NE;
        }

        if (lq <= l && r <= rq) {
            return t[v];
        }

        int mid = (l + r) / 2;
        return get(2 * v + 1, l, mid, lq, rq)
        .merge(get(2 * v + 2, mid, r, lq, rq));
    }

    void update(int v, int l, int r, int i, const Node &x) {
        if (i < l || r <= i) {
            return;
        }

        if (l + 1 == r) {
            t[v] = x;
            return;
        }

        int mid = (l + r) / 2;
        update(2 * v + 1, l, mid, i, x);
        update(2 * v + 2, mid, r, i, x);
        t[v] = t[2 * v + 1]
        .merge(t[2 * v + 2]);
    }
};


vector<ll> rev(vector<ll> a) {
    reverse(a.begin(), a.end());
    return a;
}


vector<ll> res(vector<ll> a) {
    for (int i = 0; i < a.size(); i++) {
        a[i] = a.size() - a[i] + 1;
    }
    return a;
}


vector<ll> inv(vector<ll> a) {
    vector<ll> result(a.size());
    for (int i = 0; i < a.size(); i++) {
        result[a[i] - 1] = i + 1;
    }
    return result;
}


constexpr ll MOD = 998244353;


ll binpow(ll a, ll p) {
    ll res = 1;
    while (p) {
        if (p % 2 == 0) {
            a *= a;
            a %= MOD;
            p /= 2;
        } else {
            p--;
            res *= a;
            res %= MOD;
        }
    }
    return res;
}


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

    ll n, k;
    cin >> n;
    vector<ll> a(n), b(n), p(n);
    for (int i = 0; i < n; i++) cin >> a[i] >> b[i];
    for (int i = 0; i < n; i++) cin >> p[i];

    vector<vector<ll>> dp(n + 1, vector<ll>(n + 1, LLONG_MIN));

    dp[0][0] = 0;
    ll answer = 0;
    for (int i = 1; i <= n; i++) {
        for (int t = 0; t < i; t++) {
            /* if (t != 0 && p[t - 1] != -1 && p[t - 1] > i) {
                continue;
            } */
            for (int prev_t = 0; prev_t <= t; prev_t++) {
                if (dp[i - 1][prev_t] == LLONG_MIN) continue;
                dp[i][t] = max(dp[i][t], dp[i - 1][prev_t] + (a[i - 1] + t * b[i - 1]));
                answer = max(answer, dp[i][t]);
            }
        }
    }
    cout << answer;
}
