AtCode ABC123 - D - Cake 123

标签

  • 全搜索、优先队列

题目地址

D - Cake 123

  • https://atcoder.jp/contests/abc123/tasks/abc123_d

问题描述

The Patisserie AtCoder sells cakes with number-shaped candles. There are X, Y and Z kinds of cakes with 1-shaped, 2-shaped and 3-shaped candles, respectively. Each cake has an integer value called deliciousness, as follows:

  • The deliciousness of the cakes with 1-shaped candles are A 1 _1 1, A 2 _2 2, …, A X _X X.
  • The deliciousness of the cakes with 2-shaped candles are B 1 _1 1, B 2 _2 2, …, B Y _Y Y.
  • The deliciousness of the cakes with 3-shaped candles are C 1 _1 1, C 2 _2 2, …, C Z _Z Z.

Takahashi decides to buy three cakes, one for each of the three shapes of the candles, to celebrate ABC 123.
There are X × \times × Y × \times × Z such ways to choose three cakes.
We will arrange these X × \times × Y × \times × Z ways in descending order of the sum of the deliciousness of the cakes.
Print the sums of the deliciousness of the cakes for the first, second, …, K-th ways in this list.

Constraints

  • 1 ≤ \leq X ≤ \leq 1 000
  • 1 ≤ \leq Y ≤ \leq 1 000
  • 1 ≤ \leq Z ≤ \leq 1 000
  • 1 ≤ \leq K ≤ \leq min(3 000, X × \times × Y × \times × Z)
  • 1 ≤ \leq A_i ≤ \leq 10 000 000 000
  • 1 ≤ \leq B_i ≤ \leq 10 000 000 000
  • 1 ≤ \leq C_i ≤ \leq 10 000 000 000
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

X Y Z K
A1 A2 A3 ... AX
B1 B2 B3 ... BY
C1 C2 C3 ... CZ

Output

Print K lines. The i-th line should contain the i-th value stated in the problem statement.


Sample Input 1

2 2 2 8
4 6
1 5
3 8

Sample Output 1

19
17
15
14
13
12
10
8

There are 2 × \times × 2 × \times × 2 = 8ways to choose three cakes, as shown below in descending order of the sum of the deliciousness of the cakes:

  • (A 2 _2 2, B 2 _2 2, C 2 _2 2): 6 + 5 + 8 = 19
  • (A 1 _1 1, B 2 _2 2, C 2 _2 2): 4 + 5 + 8 = 17
  • (A 2 _2 2, B 1 _1 1, C 2 _2 2): 6 + 1 + 8 = 15
  • (A 2 _2 2, B 2 _2 2, C 1 _1 1): 6 + 5 + 3 = 14
  • (A 1 _1 1, B 1 _1 1, C 2 _2 2): 4 + 1 + 8 = 13
  • (A 1 _1 1, B 2 _2 2, C 1 _1 1): 4 + 5 + 3 = 12
  • (A 2 _2 2, B 1 _1 1, C 1 _1 1): 6 + 1 + 3 = 10
  • (A 1 _1 1, B 1 _1 1, C 1 _1 1): 4 + 1 + 3 = 8

Sample Input 2

3 3 3 5
1 10 100
2 20 200
1 10 100

Sample Output 2

400
310
310
301
301

There may be multiple combinations of cakes with the same sum of the deliciousness. For example, in this test case, the sum of A 1 _1 1, B 3 _3 3, C 3 _3 3and the sum of A 3 _3 3, B 3 _3 3, C 1 _1 1are both 301. However, they are different ways of choosing cakes, so 301 occurs twice in the output.


Sample Input 3

10 10 10 20
7467038376 5724769290 292794712 2843504496 3381970101 8402252870 249131806 6310293640 6690322794 6082257488
1873977926 2576529623 1144842195 1379118507 6003234687 4925540914 3902539811 3326692703 484657758 2877436338
4975681328 8974383988 2882263257 7690203955 514305523 6679823484 4263279310 585966808 3752282379 620585736

Sample Output 3

23379871545
22444657051
22302177772
22095691512
21667941469
21366963278
21287912315
21279176669
21160477018
21085311041
21059876163
21017997739
20703329561
20702387965
20590247696
20383761436
20343962175
20254073196
20210218542
20150096547

Note that the input or output may not fit into a 32-bit integer type.

题意

  • 比较简单:给定x,y,z三个整数作为数组a,b,c的长度,把ai,bi,ci相乘得到一个数字,共有xyz种排列方法,输出结果最大前k个值

思路

  1. 全排列很可能会超时,所以要在全排列的基础上减少push的次数,减少循环次数
  2. 将a,b,c三个数组先按降序排序确保先取到是较大的值,(a + 1) * (b + 1) * (c + 1)保证只取到k个值左右的数据,尽可能减少了循环次数

题解

  • 题解
  • AtCoder Beginner Contest 123 D

小码匠

  • 20ms
void coder_solution() {
    // 提升cin、cout效率
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    long long x, y, z, k;
    cin >> x >> y >> z >> k;
    vector a(x);
    vector b(y);
    vector c(z);
    for (int i = 0; i < x; i++) {
        cin >> a[i];
    }
    sort(a.begin(), a.end(), greater());
    for (int i = 0; i < y; i++) {
        cin >> b[i];
    }
    sort(b.begin(), b.end(), greater());
    for (int i = 0; i < z; i++) {
        cin >> c[i];
    }
    sort(c.begin(), c.end(), greater());
    vector vll;
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < y; j++) {
            for (int s = 0; s < z; s++) {
                if ((i + 1) * (j + 1) * (s + 1) <= k) {
                    vll.push_back(a[i] + b[j] + c[s]);
                } else {
                    break;
                }
            }
        }
    }
    sort(vll.begin(), vll.end(), greater());
    for (int i = 0; i < k; i++) {
        cout << vll[i] << endl;
    }
}

参考题解

  • 529ms
#include 

using namespace std;

typedef long long ll;
const ll MOD = 1000000007ll;

int x, y, z, k;
ll a[1252], b[1252], c[1252];

int main() {
    scanf("%d%d%d%d", &x, &y, &z, &k);

    for (int i = 0; i < x; i++) {
        scanf("%lld", a + i);
    }

    for (int i = 0; i < y; i++) {
        scanf("%lld", b + i);
    }

    for (int i = 0; i < z; i++) {
        scanf("%lld", c + i);
    }

    multiset Q;
    Q.insert(0);
    int aaa[] = {x, y, z};
    ll *bbb[] = {a, b, c};

    for (int t = 0; t < 3; t++) {
        int n = aaa[t];
        ll *ar = bbb[t];
        multiset R;
        while (Q.size()) {
            ll v = *Q.begin();
            Q.erase(Q.begin());
            for (int i = 0; i < n; i++) {
                R.insert(v + ar[i]);
            }
            while (R.size() > k) {
                R.erase(R.begin());
            }
        }
        Q = R;
    }
    auto it = Q.rbegin();
    while (it != Q.rend()) {
        printf("%lld\n", *it);
        it++;
    }
    return 0;
}

参考题解

  • 53ms
#include 
#include 
#include 
#include 

using namespace std;
using lint = long long;
const lint mod = 256;

template
void cins(itr first, itr last) {
    for (auto i = first; i != last; i++) {
        cin >> (*i);
    }
}

using p = pair;

int main() {
    int X, Y, Z, K;

    cin >> X >> Y >> Z >> K;
    lint A[X], B[Y], C[Z];
    cins(A, A + X);
    cins(B, B + Y);
    cins(C, C + Z);
    sort(C, C + Z, greater());

    priority_queue

pairs; for (int i = 0; i < X; i++) { for (int j = 0; j < Y; j++) { pairs.push({A[i] + B[j] + C[0], 0}); } } for (int i = 0; i < K; i++) { auto top = pairs.top(); pairs.pop(); cout << top.first << endl; if (top.second == Z - 1) { continue; } pairs.push({top.first - C[top.second] + C[top.second + 1], top.second + 1}); } }

参考题解

  • 391ms
#include
#include
#include

using namespace std;
#define REP(i, m, n) for(int i=(int)(m) ; i < (int) (n) ; ++i)
#define rep(i, n) REP(i,0,n)
using ll = long long;
const int inf = 1e9 + 7;
const ll longinf = 1LL << 60;
const ll mod = 1e9 + 7;

int main() {
    ll x, y, z, k;

    cin >> x >> y >> z >> k;
    ll a[x], b[y], c[z];

    rep(i, x) cin >> a[i];
    rep(i, y) cin >> b[i];
    rep(i, z) cin >> c[i];

    vector cur;
    rep(i, x)
        rep(j, y) {
            cur.push_back(a[i] + b[j]);
        }

    sort(cur.rbegin(), cur.rend());
    if (cur.size() > k) {
        cur.resize(k);
    }
    vector res;
    rep(i, cur.size())
        rep(j, z) {
            res.push_back(cur[i] + c[j]);
        }

    sort(res.rbegin(), res.rend());
    rep(i, k) {
        cout << res[i] << endl;
    }

    return 0;
}

复盘

心得:

  • 数据结构要选用得当
  • 本题毕竟是D级别问题,全排列只适用于有部分分赛制的比赛,对于AtCode“一错满盘输”的赛制并不适用

待补知识点

  • 优先队列语法

你可能感兴趣的:(【数据结构】,算法,c++)