KEYENCE Programming Contest 2024(AtCoder Beginner Contest 374)

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” 结尾。

步骤:

  1. 读取字符串 ( S )。
  2. 获取字符串的长度,并检查最后三个字符是否依次为 ‘s’、‘a’、‘n’。
  3. 如果是,输出 “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;否则,输出第一个不同字符的位置。

解题思路:

这是一个字符串比较的问题,要求输出第一个不同字符的位置,或者确认两个字符串完全相同。

步骤:

  1. 读取两个字符串 ( S ) 和 ( T )。
  2. 比较它们的字符,逐一检查是否相等,直到找到第一个不同的字符。
  3. 如果找到了不同字符,输出其索引;如果一个字符串较短,直接输出较短字符串结束后的索引。
  4. 如果两个字符串完全相同,输出 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 )。要求将所有部门分成两组,使得两组人数的较大者尽可能小。

解题思路:

这是一个典型的分组问题,类似于背包问题。目标是将人数总和尽可能平分,使得两组中人数较大者最小。

步骤

  1. 将问题视作背包问题,寻找一种分组方式,使得两组人数尽量平衡。
  2. 通过递归或者动态规划计算所有可能的分组人数。
  3. 最终选取满足条件的最小较大者。

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 来寻找最短路径,并标记尽量多的格子。由于每个格子只能被标记一次,问题可归结为如何在最短步数内遍历尽可能多的格子。

步骤

  1. 从起始点开始,使用 BFS 搜索。
  2. 标记经过的每一个格子,确保不会重复访问。
  3. 记录步数,并在结束时统计总共标记的格子数。

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) )。请问在预算范围内可以实现的最大生产能力是多少?

解题思路:

这是一个典型的预算优化问题,要求在给定预算限制下最大化生产能力。

步骤:

  1. 问题分析:我们需要在预算限制内,通过不同工序的调整来最大化生产能力。
  2. 二分查找:由于生产能力和预算之间存在单调关系,可以使用二分查找来确定最大可能的生产能力。
  3. 贪心计算预算需求:对于每个工序,通过当前生产能力需求计算所需费用。使用贪心算法计算每个工序在给定预算下的最优处理方式。
  4. 判断是否满足预算:对于每个二分出的生产能力,计算总费用是否在预算之内。

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) )。

求如何安排发货,以使总的不满意度最小。

解题思路:

这是一个典型的动态规划问题,目标是通过最优发货安排来最小化总不满意度。我们可以按照以下步骤进行:

  1. 订单排序:根据到达时间 ( T_i ) 对订单进行排序。
  2. 动态规划:使用动态规划来跟踪到当前订单的最小不满意度:
    • 使用二维数组 ( dp[i][j] ),表示在第 ( i ) 天发货第 ( j ) 批订单的最小不满意度。
    • 对于每个订单,计算当前发货安排对后续订单的影响。
  3. 贪心选择:每次发货时,优先选择不满意度最低的组合。

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值