AtCoder Beginner Contest 373
题目链接:AtCoder Beginner Contest 373 - AtCoder
A:September
题目链接:September
题目描述:
输入12个字符串,输出这些字符串中满足条件的个数。条件是:第i个字符串应当由小写字母组成,且其长度为i。
解题思路:
遍历每个字符串,判断其长度是否为i,且所有字符是否都是小写字母。如果满足条件,计数加1。
C++代码实现:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define close ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
void solved() {
int ans = 0;
for (int i = 1; i <= 12; i++) {
string s;
cin >> s;
if(s.length() == i) {
bool flag = true;
for (int j = 0; j < i; j++) {
if(!(s[j] >= 'a' && s[j] <= 'z')) {
flag = false;
break;
}
}
ans += flag;
}
}
cout << ans << endl;
}
signed main() {
close;
solved();
return 0;
}
B:1D Keyboard
题目链接:1D Keyboard
题目描述:
输入一个由字母 A 到 Z 组成的排列,计算从字母 A 开始依次移动到 Z 的总移动距离。
解题思路:
首先记录每个字母的位置。然后,从 A 开始,计算从当前字母到下一个字母的距离并累计。
C++代码实现:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
void solved() {
map<char, int> mp;
string s;
cin >> s;
for (int i = 0; i < s.length(); i++) {
mp[s[i]] = i;
}
int cnt = mp['A'];
int ans = 0;
for (int i = 1; i < 26; i++) {
char go = 'A' + i;
ans += abs(mp[go] - cnt);
cnt = mp[go];
}
cout << ans << endl;
}
signed main() {
close;
solved();
return 0;
}
C:Max Ai + Bj
题目链接:Max Ai + Bj
题目描述:
给定两个数组 A 和 B,找出 A 中最大的元素和 B 中最大的元素之和。
解题思路:
遍历数组 A 和 B,分别找到它们的最大值,然后输出这两个最大值的和。
C++代码实现:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
void solved() {
int n;
cin >> n;
vector<int> A(n), B(n);
for (int i = 0; i < n; i++) cin >> A[i];
for (int i = 0; i < n; i++) cin >> B[i];
int maxA = *max_element(A.begin(), A.end());
int maxB = *max_element(B.begin(), B.end());
cout << maxA + maxB << endl;
}
signed main() {
close;
solved();
return 0;
}
D:Hidden Weights
题目链接:Hidden Weights
题目描述:
给定一个有向图,包含N个节点和M条边,边有权重。对于每一条边,从节点u指向节点v,并有权重w,需要满足value[v] - value[u] = w。问题要求在所有节点之间赋值,并确保所有等式成立。
解题思路:
从根节点开始广度优先搜索(BFS),给根节点赋值0,然后根据边的权重推算其他节点的值。如果图不连通,则每个连通块单独进行 BFS。
C++代码实现:
#include<bits/stdc++.h>
using namespace std;
#define close ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl '\n'
#define int long long
const int N = 2e5 + 10;
int vis[N];
vector<pair<int, int>> edg[N];
int n, m;
int v[N];
void bfs(int id) {
queue<int> q;
q.push(id);
while(!q.empty()) {
int who = q.front();
q.pop();
for(auto [ne, w] : edg[who]) {
if(!vis[ne]) {
vis[ne] = 1;
v[ne] = v[who] + w;
q.push(ne);
}
}
}
}
void solved() {
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
edg[u].push_back({v, w});
edg[v].push_back({u, -w});
}
for (int i = 1; i <= n; i++) {
if(!vis[i]) {
v[i] = 0;
vis[i] = 1;
bfs(i);
}
}
for (int i = 1; i <= n; i++) {
if(i > 1) {
cout << " ";
}
cout << v[i];
}
}
signed main() {
close;
solved();
return 0;
}
E:How to Win the Election
题目描述:
有N个人参加选举,一共有K张选票,最终会有M个人当选。部分票数已经确定,对于一个特定的候选人,计算他需要拿到的最少选票数以确保当选。
解题思路:
贪心策略:只需要关注那些能够对该候选人构成威胁的人,争取刚好进入前M名即可。
C++代码实现:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
void solved()
{
int n, m, k;
cin >> n >> m >> k;
vector<int> arr(n);
int total = 0;
for (auto &v : arr)
{
cin >> v;
total += v;
}
int rem = k - total;
if (n <= m)
{
for (int i = 0; i < n; i++)
{
if (i > 0)
{
cout << " ";
}
cout << 0;
}
cout << endl;
return;
}
vector<int> brr(arr);
sort(brr.begin(), brr.end());
vector<int> index(n);
iota(index.begin(), index.end(), 0);
sort(index.begin(), index.end(), [&](int i, int j)
{ return arr[i] < arr[j]; });
vector<int> pre(n + 1, 0);
for (int i = 0; i < n; i++)
{
pre[i + 1] = pre[i] + brr[i];
}
vector<int> ans(n, -1);
for (int i = 0; i < n; i++)
{
int l = 0, r = rem, result = -1;
while (l <= r)
{
int mid = (l + r) >> 1;
int right = upper_bound(brr.begin(), brr.end(), brr[i] + mid) - brr.begin();
int left = n - m;
if (i >= n - m)
{
--left;
}
int need = 0;
if (right > left)
{
need += (right - left) * (brr[i] + mid + 1) - (pre[right] - pre[left]);
}
if (left <= i && i < right)
{
need--;
}
else
{
need += mid;
}
if (need <= rem)
{
l = mid + 1;
}
else
{
result = mid;
r = mid - 1;
}
}
ans[index[i]] = result;
}
for (int i = 0; i < n; i++)
{
if (i > 0)
{
cout << " ";
}
cout << ans[i];
}
cout << endl;
}
signed main()
{
close;
solved();
return 0;
}
F:Knapsack with Diminishing Values
题目链接:Knapsack with Diminishing Values
题目描述:
给定N种物品,每种物品的权重为w,价值为v。背包容量为W。某个物品的快乐值贡献为 kv - k*k
,其中k为选取的个数。目标是让总快乐值最大化。
解题思路:
将 kv - k*k
拆解成多个项,发现每次多选一件物品的增量贡献为 v - 2
。因此可以通过动态规划实现求解。
C++代码实现:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 30000;
const int inf = 1e18;
vector<int> edg[N];
void solved() {
int N, W;
cin >> N >> W;
for (int i = 1; i <= N; i++) {
int w, v;
cin >> w >> v;
edg[w].push_back(v);
}
vector<int> dp(W + 1, -inf);
dp[0] = 0;
for (int i = 1; i <= W; i++) {
if (edg[i].empty()) {
continue;
}
priority_queue<int> pq;
for (int j = 0; j < edg[i].size(); j++) {
pq.push(edg[i][j] - 1);
}
vector<int> happy(W / i + 1, 0);
for (int nums = 0; nums < W / i; nums++) {
int v = pq.top();
pq.pop();
happy[nums + 1] = happy[nums] + v;
pq.push(v - 2);
}
for (int j = W; j >= 0; j--) {
int nums = 1;
while (j + nums * i <= W) {
dp[j + nums * i] = max(dp[j + nums * i], dp[j] + happy[nums]);
++nums;
}
}
}
cout << *max_element(dp.begin(), dp.end()) << endl;
}
signed main() {
close;
solved();
return 0;
}
G:No Cross Matching
题目链接:No Cross Matching
题目描述:
二维平面上有2*N个点,其中N个点在P集合中,N个点在Q集合中,问是否可以找到N条线段连接Pi和Qj,使这些线段两两之间没有交点。
解题思路:
可以将该问题转化为最小流问题,证明线段不相交的最优条件是满足 ac + bd <= ab + cd
,即找到一组连接使得总距离最小。
C++代码实现:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 1000010;
const int inf = 1e18;
const long double C = 1.5e12;
struct Edg
{
int next, to, cap, cost;
};
Edg edg[N];
int head[N], tot = 1;
int h[N], dist[N], prePoint[N], preEdg[N];
int n, s, t;
vector<pair<int, int>> point[2];
void input()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
int x, y;
cin >> x >> y;
point[0].push_back({x, y});
}
for (int i = 1; i <= n; i++)
{
int x, y;
cin >> x >> y;
point[1].push_back({x, y});
}
}
inline long double dis(pair<int, int> a, pair<int, int> b)
{
return sqrt((a.first - b.first) * (a.first - b.first) +
(a.second - b.second) * (a.second - b.second));
}
void add(int u, int v, int cap, int cost)
{
edg[++tot] = {head[u], v, cap, cost};
head[u] = tot;
edg[++tot] = {head[v], u, 0, -cost};
head[v] = tot;
}
void build()
{
s = 2 * n;
t = 2 * n + 1;
for (int i = 0; i < n; i++)
{
add(s, i, 1, 0);
}
for (int i = 0; i < n; i++)
{
add(i + n, t, 1, 0);
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
int cost = (int)(dis(point[0][i], point[1][j]) * C + 0.5);
add(i, j + n, 1, cost);
}
}
}
int minFlow(int s, int t, int limit)
{
int flow = 0, cost = 0;
while (flow < limit)
{
fill(dist, dist + N, inf);
dist[s] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push({0, s});
while (!pq.empty())
{
auto [d, v] = pq.top();
pq.pop();
if (dist[v] < d)
continue;
for (int i = head[v]; i; i = edg[i].next)
{
Edg &e = edg[i];
if (e.cap > 0)
{
int to = e.to;
int cost_vw = e.cost + h[v] - h[to];
if (dist[to] > dist[v] + cost_vw)
{
dist[to] = dist[v] + cost_vw;
prePoint[to] = v;
preEdg[to] = i;
pq.emplace(dist[to], to);
}
}
}
}
if (dist[t] == inf)
{
break;
}
for (int v = 0; v <= t; ++v)
{
if (dist[v] < inf)
h[v] += dist[v];
}
int cnt = limit - flow;
for (int v = t; v != s; v = prePoint[v])
{
cnt = min(cnt, edg[preEdg[v]].cap);
}
flow += cnt;
cost += cnt * h[t];
for (int v = t; v != s; v = prePoint[v])
{
edg[preEdg[v]].cap -= cnt;
edg[preEdg[v] ^ 1].cap += cnt;
}
}
if (flow < limit)
{
cout << "-1" << endl;
exit(0);
}
return cost;
}
void output()
{
vector<int> ans(n, -1);
for (int i = 0; i < n; ++i)
{
for (int e = head[i]; e; e = edg[e].next)
{
Edg &ed = edg[e];
if (ed.to >= n && ed.to < 2 * n && ed.cap == 0)
{
ans[i] = ed.to - n + 1;
break;
}
}
}
for (int i = 0; i < n; ++i)
{
cout << ans[i] << " \n"[i == n - 1];
}
}
signed main()
{
close;
input();
build();
int limit = n;
int minCost = minFlow(s, t, limit);
output();
return 0;
}
以上是对 AtCoder Beginner Contest 373 中所有题目的解题思路和代码实现,希望对你有所帮助。