voidsolve(){ int n, k; cin >> n >> k; for (int i = 1; i <= n; ++i) cin >> a[i]; for (int i = 1; i <= n; ++i) { int tmp = a[i]; for (int j = 1; j <= n; ++j) { tmp += a[j]; if (tmp > 1020 || j == i) { tmp -= a[j]; continue; } for (int k = 1; k <= n; ++k) { tmp += a[k]; if (tmp > 1020 || (k == i || k == j)) { tmp -= a[k]; continue; } for (int o = 1; o <= n; ++o) { tmp += a[o]; if (tmp > 1020 || (o == i || o == j || o == k)) { tmp -= a[o]; continue; } vis[tmp] = 1; tmp -= a[o]; } tmp -= a[k]; } tmp -= a[j]; } } while (k--) { bool flag = 1; int m; cin >> m; for (int i = 1; i <= m; ++i) { int x; cin >> x; if (flag && !vis[x * 4]) { flag = 0; } } cout << (flag ? "Yes" : "No") << endl; } }
B.芬兰木棋—贪心+map容器
题意:一个根据芬兰游戏改变简化的题。一个人叫哲哲站在 (0,0) 处,他的周围都放着许多木棋(保证没有位置重复或者在原点的),每个木棋上有个正整数代表分数。这个人每次选择一个方向,他有以下两种操作选择:击倒该方向上离着自己最近的木棋并获得木棋的分数;或者击倒该方向上离着自己最近的 k 个木桩自闭并获得击倒根数的分数(也就是 k 分)。现在这个人想拿到最多分并且求出拿到最多分数时需要最少操作次数
voidsolve(){ int n; cin >> n; for (int i = 1; i <= n; ++i) { int x, y, z; cin >> x >> y >> z; int xx = x, yy = y; if (x == 0) y /= abs(y); elseif (y == 0) x /= abs(x); else { int gcd = __gcd(abs(x), abs(y)); x /= gcd, y /= gcd; } mp[pii(y, x)].push_back(pii(xx * xx + yy * yy, z)); } int ans = 0, cnt = 0; for (auto &e1 : mp) { sort(e1.second.begin(), e1.second.end()); int tmp = 0; for (auto &e2 : e1.second) { if (e2.second == 1) ++tmp; else { ans = ans + tmp + e2.second; if (!tmp) ++cnt; else cnt += 2; tmp = 0; } } if (tmp) ans = ans + tmp, ++cnt; } cout << ans << ' ' << cnt << endl; }
C.打怪升级—模拟思维+最短路打印路径
题意:有 n 个点形成的无向带权连通图,路径上有怪物路路过时需要消耗能量击败他们同时可以得到价值。需要完成两件事:
先确定一个合适的起点,要求这个起点到其他点的能量消耗最大值尽可能小,如果有多个这样的点选择靠前的点
而后有 k 个点询问,帮助玩家确定从选定起点出发到指定询问点所需要走的路径,要求这个路径消耗的能量值尽可能小,如果有多条这样的路径选择获得价值最大的
int n, m, d; int fa[maxn]; bool vis[maxn]; vector<int> tmp, ans, G[maxn]; vector<pii> road, ask[maxn];
intfind(int x){ return x == fa[x] ? x : fa[x] = find(fa[x]); }
voidjoin(int x, int y){ int fx = find(x), fy = find(y); if (fx == fy) return; fa[fx] = fy; }
voidsolve(){ cin >> n >> m >> d; for (int i = 1; i <= n; ++i) fa[i] = i; //init for (int i = 1; i <= m; ++i) { //存边 int u, v; cin >> u >> v; road.push_back(pii(u, v)); G[u].push_back(v), G[v].push_back(u); } tmp.resize(d + 1); //倒着离线操作 for (int i = 1; i <= d; ++i) { int c, q; cin >> c >> q; tmp[i] = c, vis[c] = 1; //中毒的城市 for (int j = 1; j <= q; ++j) { //记录询问 int u, v; cin >> u >> v; ask[i].push_back(pii(u, v)); } } for (auto &e : road) { //先建立连接的城市 int st = e.first, ed = e.second; if (!vis[st] && !vis[ed]) join(st, ed); } for (int i = d; i >= 1; --i) { //倒着处理每一天 int cnt = 0; //记录答案 for (auto &e : ask[i]) { //询问 int x = e.first, y = e.second; if (find(x) != find(y)) ++cnt; //说明道路没有关闭 } ans.push_back(cnt); for (auto &e : G[tmp[i]]) { //处理新的路 if (vis[e]) continue; else join(tmp[i], e); } vis[tmp[i]] = 0; } for (auto it = ans.rbegin(); it != ans.rend(); ++it) cout << *it << endl; }