KEYENCE Programming Contest 2024(AtCoder Beginner Contest 374)
题目链接: KEYENCE Programming Contest 2024(AtCoder Beginner Contest 374) - AtCoder
A - Takahashi san 2
题目链接: A - Takahashi san 2 (atcoder.jp)
题目描述:
给定一个由小写字母组成的字符串 ( S ),如果 ( S ) 以 “san” 结尾,输出 “Yes”,否则输出 “No”。
解题思路:
这是一个简单的字符串匹配问题,要求判断字符串是否以特定后缀 “san” 结尾。
步骤:
- 读取字符串 ( S )。
- 获取字符串的长度,并检查最后三个字符是否依次为 ‘s’、‘a’、‘n’。
- 如果是,输出 “Yes”;否则输出 “No”。
这种问题可以通过简单的字符串索引操作解决,复杂度为 ( O(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)
vector<array<int, 3>> arr;
void solved()
{
string s;
cin>>s;
int len = s.length();
if(s[len-3]=='s' && s[len-2]=='a'&&s[len-1]=='n')
{
cout << "Yes";
}
else
{
cout << "No";
}
}
signed main()
{
close;
solved();
}
B - Unvarnished Report
题目链接: B - Unvarnished Report (atcoder.jp)
题目描述:
给定两个字符串 ( S ) 和 ( T ),如果它们完全相同,输出 0;否则,输出第一个不同字符的位置。
解题思路:
这是一个字符串比较的问题,要求输出第一个不同字符的位置,或者确认两个字符串完全相同。
步骤:
- 读取两个字符串 ( S ) 和 ( T )。
- 比较它们的字符,逐一检查是否相等,直到找到第一个不同的字符。
- 如果找到了不同字符,输出其索引;如果一个字符串较短,直接输出较短字符串结束后的索引。
- 如果两个字符串完全相同,输出 0。
注意:如果字符串长度不等且短字符串完全匹配长字符串的前缀,则不同的字符位置是长度较短的字符串结束后的第一个字符。
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)
vector<array<int, 3>> arr;
void solved()
{
string s1;
string s2;
cin >> s1 >> s2;
if(s1==s2)
{
cout << 0;
}
else
{
int len1 = s1.length();
int len2 = s2.length();
int minNum = min(len1, len2);
int ans = -2;
for (int i = 0; i < minNum;i++)
{
if(s1[i]!=s2[i])
{
ans = i;
break;
}
}
++ans;
if(ans == -1)
{
ans = minNum + 1;
}
cout << ans;
}
}
signed main()
{
close;
solved();
}
C - Separated Lunch
题目链接: C - Separated Lunch (atcoder.jp)
题目描述:
KEYENCE 总部的员工需要分成两组 A 和 B,错开午休时间。总部有 ( N ) 个部门,部门 ( i ) 的人数为 ( K_i )。要求将所有部门分成两组,使得两组人数的较大者尽可能小。
解题思路:
这是一个典型的分组问题,类似于背包问题。目标是将人数总和尽可能平分,使得两组中人数较大者最小。
步骤:
- 将问题视作背包问题,寻找一种分组方式,使得两组人数尽量平衡。
- 通过递归或者动态规划计算所有可能的分组人数。
- 最终选取满足条件的最小较大者。
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 split(int idx, int end, const vector<int> &nums, vector<int> &sums, int current_sum)
{
if (idx == end)
{
sums.push_back(current_sum);
return;
}
split(idx + 1, end, nums, sums, current_sum);
split(idx + 1, end, nums, sums, current_sum + nums[idx]);
}
void solved()
{
int n;
cin >> n;
vector<int> nums(n);
int total = 0;
for (auto &v : nums)
{
cin >> v;
total += v;
}
int mid = n / 2;
vector<int>sums1, sums2;
split(0, mid, nums, sums1, 0);
split(mid, n, nums, sums2, 0);
sort(sums2.begin(), sums2.end());
int half = total / 2;
int minMax = LLONG_MAX;
for (auto s1 : sums1)
{
if (s1 > half)
{
continue;
}
auto it = upper_bound(sums2.begin(), sums2.end(), half - s1);
if (it != sums2.begin())
{
--it;
int s2 = *it;
int sum1 = s1 + s2;
int sum2 = total - sum1;
minMax = min(minMax, max(sum1, sum2));
}
}
cout << minMax << endl;
}
signed main()
{
close;
solved();
}
D - Laser Marking
题目链接: D - Laser Marking (atcoder.jp)
题目描述:
给定一个 ( H imes W ) 的网格,使用激光在其中进行标记。激光可以沿着上下左右四个方向移动,要求用最少的步数标记尽量多的格子。
解题思路:
这是一个经典的图搜索问题,可以使用 BFS 来寻找最短路径,并标记尽量多的格子。由于每个格子只能被标记一次,问题可归结为如何在最短步数内遍历尽可能多的格子。
步骤:
- 从起始点开始,使用 BFS 搜索。
- 标记经过的每一个格子,确保不会重复访问。
- 记录步数,并在结束时统计总共标记的格子数。
C++代码实现:
#include <map>
#include <set>
#include <fstream>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdio>
#include <bitset>
#include <iomanip>
#define endl '\n'
#define int long long
#define Max(a, b) (((a) > (b)) ? (a) : (b))
#define Min(a, b) (((a) < (b)) ? (a) : (b))
#define BoBoowen ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;
int n, S, T;
int f[114], vis[114];
double ans = 1e18;
struct node
{
int x[2];
int y[2];
} a[1145];
double dis(double x, double y, double a, double b)
{
return sqrt(1.0 * (1.0 * x - a) * (x - a) + 1.0 * (1.0 * y - b) * (y - b));
}
void dfs(int x)
{
if (x == n + 1)
{
int x = 0, y = 0;
double res = 0;
for (int s = 0; s < (1 << n); s++)
{
res = 0;
x = 0;
y = 0;
for (int i = 1; i <= n; i++)
if (s & (1 << i - 1))
{
res += dis(x, y, a[f[i]].x[0], a[f[i]].y[0]) / 1.0 / S + dis(a[f[i]].x[0], a[f[i]].y[0], a[f[i]].x[1], a[f[i]].y[1]) / 1.0 / T;
x = a[f[i]].x[1];
y = a[f[i]].y[1];
}
else
{
res += dis(x, y, a[f[i]].x[1], a[f[i]].y[1]) / 1.0 / S + dis(a[f[i]].x[0], a[f[i]].y[0], a[f[i]].x[1], a[f[i]].y[1]) / 1.0 / T;
x = a[f[i]].x[0];
y = a[f[i]].y[0];
}
ans = min(ans, res);
}
return;
}
for (int i = 1; i <= n; i++)
{
if (vis[i] == 0)
{
vis[i] = 1;
f[x] = i;
dfs(x + 1);
vis[i] = 0;
}
}
}
signed main()
{
cin >> n >> S >> T;
for (int i = 1; i <= n; i++)
{
cin >> a[i].x[0];
cin >> a[i].y[0];
cin >> a[i].x[1];
cin >> a[i].y[1];
}
dfs(1);
cout << fixed << setprecision(8) << ans << endl;
}
E - Sensor Optimization Dilemma 2
题目链接: E - Sensor Optimization Dilemma 2 (atcoder.jp)
题目描述:
有 ( N ) 道工序,每道工序每天可以加工 ( A_i ) 个产品,处理的单价是 ( P_i )。总预算为 ( X ) 日元,目标是最大化每天的生产能力 ( W_i ),其中 ( W = \min(W_i) )。请问在预算范围内可以实现的最大生产能力是多少?
解题思路:
这是一个典型的预算优化问题,要求在给定预算限制下最大化生产能力。
步骤:
- 问题分析:我们需要在预算限制内,通过不同工序的调整来最大化生产能力。
- 二分查找:由于生产能力和预算之间存在单调关系,可以使用二分查找来确定最大可能的生产能力。
- 贪心计算预算需求:对于每个工序,通过当前生产能力需求计算所需费用。使用贪心算法计算每个工序在给定预算下的最优处理方式。
- 判断是否满足预算:对于每个二分出的生产能力,计算总费用是否在预算之内。
C++代码实现:
#include <map>
#include <set>
#include <fstream>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdio>
#include <bitset>
#include <iomanip>
#define endl '\n'
#define int long long
#define Max(a, b) (((a) > (b)) ? (a) : (b))
#define Min(a, b) (((a) < (b)) ? (a) : (b))
#define BoBoowen ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;
const int N = 110;
int n, m;
int a[N], p[N], b[N], q[N];
signed main()
{
BoBoowen;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
cin >> a[i] >> p[i] >> b[i] >> q[i];
if (p[i] * b[i] > q[i] * a[i])
{
swap(a[i], b[i]);
swap(p[i], q[i]);
}
}
int l = 0, r = 1e9;
while (l < r)
{
int mid = l + r + 1 >> 1;
int need = 0;
for (int i = 1; i <= n; ++i)
{
int mn = 1e9;
int cnt = (mid + a[i] - 1) / a[i];
for (int j = Max(0, cnt - 1000); j <= cnt; ++j)
{
int lef = mid - j * a[i];
int now = j * p[i];
if (lef > 0)
{
now += ((lef + b[i] - 1) / b[i]) * q[i];
}
mn = Min(mn, now);
}
need += mn;
}
if (need <= m)
{
l = mid;
}
else
{
r = mid - 1;
}
}
cout << l << endl;
}
F - Shipping
题目链接: F - Shipping (atcoder.jp)
题目描述:
有 ( N ) 个订单,每个订单将在第 ( T_i ) 天到达。每次最多可以发货 ( K ) 个订单,并且每次发货后必须间隔 ( X ) 天才能再次发货。
每个订单的发货时间越晚,不满意度越高。不满意度的计算方式是:如果订单 ( i ) 在第 ( S_i ) 天发货,则该订单的不满意度为 ( (S_i - T_i) )。
求如何安排发货,以使总的不满意度最小。
解题思路:
这是一个典型的动态规划问题,目标是通过最优发货安排来最小化总不满意度。我们可以按照以下步骤进行:
- 订单排序:根据到达时间 ( T_i ) 对订单进行排序。
- 动态规划:使用动态规划来跟踪到当前订单的最小不满意度:
- 使用二维数组 ( dp[i][j] ),表示在第 ( i ) 天发货第 ( j ) 批订单的最小不满意度。
- 对于每个订单,计算当前发货安排对后续订单的影响。
- 贪心选择:每次发货时,优先选择不满意度最低的组合。
C++代码实现:
#include <map>
#include <set>
#include <fstream>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdio>
#include <bitset>
#include <iomanip>
#define endl '\n'
#define int long long
#define Max(a, b) (((a) > (b)) ? (a) : (b))
#define Min(a, b) (((a) < (b)) ? (a) : (b))
#define BoBoowen ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;
const int N = 105;
const int inf = 1e9;
const int INF = 1e18;
int n, K, X;
int f[N][N][N], a[N], s[N];
signed main()
{
BoBoowen;
cin >> n >> K >> X;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
for (int i = 0; i <= n; ++i)
{
for (int j = 0; j <= n; ++j)
{
for (int k = 0; k <= n; ++k)
{
f[i][j][k] = INF;
}
}
}
for (int i = 1; i <= K; ++i)
{
f[i][i][0] = 1ll * a[i] * i - s[i];
}
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= n; ++j)
{
for (int k = 0; k <= n; ++k)
{
for (int l = i + 1; l <= n; ++l)
{
if (l - i > K)
{
continue;
}
if (f[i][j][k] != INF)
{
if (a[j] + k * X + X <= a[l])
{
f[l][l][0] = Min(f[l][l][0], f[i][j][k] + a[l] * (l - i) - (s[l] - s[i]));
}
if (a[j] + k * X + X >= a[l])
{
f[l][j][k + 1] = Min(f[l][j][k + 1], f[i][j][k] + (a[j] + k * X + X) * (l - i) - (s[l] - s[i]));
}
}
}
}
}
}
int ans = INF;
for (int i = 1; i <= n; ++i)
{
for (int j = 0; j <= n; ++j)
{
ans = Min(ans, f[n][i][j]);
}
}
cout << ans;
}