Skip to content

Latest commit

 

History

History
56 lines (45 loc) · 2.6 KB

1129. Recommendation System.md

File metadata and controls

56 lines (45 loc) · 2.6 KB

【PAT A-1129】Recommendation System

题意概述

用户每访问一件商品,就向他推荐 K 个商品,这 K 个商品从他从前的购买过的商品中按照购买次数从高到低的顺序选择 K 个,如果有购买次数相同的,就按照商品的编号从小到大的顺序推荐。

输入输出格式

输入第一行包含两个正整数:N 和 K,分别表示查询总数和系统可以向用户推荐的最大商品数。然后在第二行中给出用户正在访问的商品的编号。为简单起见,所有商品都从 1 到 N 编号。行中的所有数字都用空格分隔。

在一行中按$query: rec[1] rec[2] …… rec[K]$的格式输出访问每个商品时的推荐商品编号。query 是用户正在访问的商品,rec[i]是系统向用户推荐的第 i 个商品。以访问频率从高到低的顺序推荐访问频率最高的前 K 个商品。如果有频率相同的情况,则推荐编号更小的商品。注意:访问第一个商品时没有输出,因为当时无法推荐任何商品。保证至少有一个输出。

数据规模

$$N\le 50000,K\le 10$$

算法设计

可定义unordered_map<gg,gg>用来存储商品及其访问频率的映射关系。利用一个 set 将目前所有的商品以频率从高到低、编号从小到大的顺序存储起来。然后每访问一个商品,就从 set 中取出前 K 个商品输出其编号即可。这里涉及两个问题,第一个问题是我们需要自定义 set 的排序方法。第二个问题是商品的访问频率一直在变化,我们如何保证 set 中商品的频率做到同步变化?办法很简单,先从 set 中删除原有商品,再插入一个具有更新后频率的商品即可。

C++代码

#include <bits/stdc++.h>
using namespace std;
using gg = long long;
struct cmp {
    bool operator()(const pair<gg, gg>& p1, const pair<gg, gg>& p2) const {
        return tie(p2.second, p1.first) < tie(p1.second, p2.first);
    }
};
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    gg ni, ki, ai;
    cin >> ni >> ki;
    cin >> ai;
    unordered_map<gg, gg> um{{ai, 1}};
    set<pair<gg, gg>, cmp> s{{ai, 1}};
    while (--ni) {
        cin >> ai;
        cout << ai << ":";
        gg c = 0;
        for (auto& i : s) {
            cout << " " << i.first;
            if (++c == ki) {  //输出达到K个商品,结束循环
                break;
            }
        }
        cout << "\n";
        s.erase({ai, um[ai]});  //从set中删除旧有频率的商品
        s.insert({ai, ++um[ai]});  //向set中插入更新频率后的商品
    }
    return 0;
}