ABC325 A-F

目录

A - Takahashi san

tag:签到

题解:

B - World Meeting

tag:签到,枚举

题解:

C - Sensors

tag:模拟,dfs/bfs,遍历

题解:

D - Printing Machine

tag:优先队列,排序

错误思路:

题解:

E - Our clients, please wait a moment

tag:最短路,dijkstra

题解:

F - Sensor Optimization Dilemma

tag:动态规划(DP

题解:


A - Takahashi san

tag:签到

题解:

读入第一个字符串,并在后面加上一个空格隔开的san即可。

B - World Meeting

tag:签到,枚举

题解:

枚举起始时间,然后把这段时间的人数加起来即可。

// 加油昂!!!
// Problem: B - World Meeting
// Contest: AtCoder - KEYENCE Programming Contest 2023 Autumn(AtCoder Beginner Contest 325)
// URL: https://atcoder.jp/contests/abc325/tasks/abc325_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;

void solve()
{
    cin >> n;
    map<int,int> mp;
    for (int i = 0; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        mp[y] += x;
    }
    int ans = 0;
    for (int i = 0; i < 24; i++)
    {
        int j = i + 9;
        int res = 0;
        for (int z = i; z < j; z++)
        {
            res += mp[z % 24];
        }
        ans = max(ans, res);
    }
    cout << ans << "\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

C - Sensors

tag:模拟,dfs/bfs,遍历

题解:

判断有几个传感器,如果是相邻的就为一个,相当于问有几个连通块,直接dfs/bfs遍历同一个连通块,然后走过的打上标记,即可统计出所有的连通块数量。

// 加油昂!!!
// Problem: C - Sensors
// Contest: AtCoder - KEYENCE Programming Contest 2023 Autumn(AtCoder Beginner Contest 325)
// URL: https://atcoder.jp/contests/abc325/tasks/abc325_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
int dx[] = {-1, 0, 1, 0, -1, -1, 1, 1}, dy[] = {0, -1, 0, 1, -1, 1, -1, 1};
char c[1010][1010];
bool f[1010][1010];
void dfs(int x, int y)
{
    f[x][y] = true;
    for (int i = 0; i < 8; i++)
    {
        int xx = x + dx[i], yy = y + dy[i];
        if (xx >= 1 && xx <= n && yy >= 1 && yy <= m && !f[xx][yy] && c[xx][yy] == '#')
        {
            dfs(xx,yy);
        }
    }
}
void solve()
{
    cin >> n >> m;
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cin >> c[i][j];
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (c[i][j] == '#' && !f[i][j])
            {
                dfs(i,j);
                ans++;
            }
        }
    }
    cout << ans << "\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

D - Printing Machine

tag:优先队列,排序

错误思路:

想法大致差不多,就是在实现的时候,理所当然的认为先进入的推出时间肯定最早,然后用该方法贪心就能做,其实不然,假设样例(1,6)(1,6)(1,6)(2,1)如果按照我的方法贪心的话,他的打印顺序是依次打印,然后打印第四个的时候可打印时间是4,因此就不能打印,但是加入我们先打印第一个,然后再打印第四个,之后打印二三个,这样就能将四个打印完,所以我们需要在每次t到达一个元素的开始时间的时候就把他加入到可打印的队列中,然后打印出队时间最早的。

题解:

读懂题意之后很容易想到贪心做法,即打印已经进入打印范围的且先出去的的那个,这样我们就需要用一个优先队列来放置可打印的产品,并每次把最先出去的那一个给先打印了,这样才能保证最优解。具体实现方式如下代码所示:

// 加油昂!!!
// Problem: D - Printing Machine
// Contest: AtCoder - KEYENCE Programming Contest 2023 Autumn(AtCoder Beginner Contest 325)
// URL: https://atcoder.jp/contests/abc325/tasks/abc325_d
// Memory Limit: 1024 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
void solve()
{
    cin >> n;
    vector<pair<int,int>> all;
    for (int i = 1; i <= n; i++)
    {
        int l, r;
        cin >> l >> r;
        all.emplace_back(l, r);
    }
    priority_queue<int, vector<int>, greater<int>> q;//小根堆,堆顶元素为最小值
    sort(all.begin(),all.end());//排序保证入队时间为从小到大,第二维不用管,因为后续优先队列会对其进行操作
    int ans = 0;
    int i = 0;//记录取到的元素位置
    for (int t = 0; ; t++)
    {
        if (q.empty())
        {
            if (i == n) break;//说明遍历完所有元素了,在队列为空时才判断,所以不会导致还有元素未打印的情况
            t = all[i].first;//因为当前没有元素了,所以我们直接将时间跳转到下一个能打印的元素的起始时间
        }
        while (i < n && t == all[i].first)//如果开始时间相同,那么我们就把他入队
        {
            q.push(all[i].first + all[i].second);
            i++;
        }
        while (q.size() && q.top() < t) q.pop();//如果队顶元素已经在当前时间之前结束了,那他就不能打印,因此我们就该删除该元素
        if (!q.empty())//如果不为空,就可以打印一个(因为当前元素的结束时间必定是大于等于t的,可打印的元素)
        {
            ans++;
            q.pop();
        }
    }
    cout << ans << "\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

E - Our clients, please wait a moment

tag:最短路,dijkstra

题解:

需要求从1走到n的最短路,其中限制条件有:刚开始是汽车且只能汽车换火车,所以我们按照题意进行两遍dijkstra,一次是坐汽车从点1到n,另一次是坐火车从点n到1,然后枚举换成点,求出最小值,ans = min(ans, dist1[i] + dist2[i]);(其中dist1代表坐汽车,dist2表示坐火车)

// 加油昂!!!
// Problem: E - Our clients, please wait a moment
// Contest: AtCoder - KEYENCE Programming Contest 2023 Autumn(AtCoder Beginner Contest 325)
// URL: https://atcoder.jp/contests/abc325/tasks/abc325_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
#define PII pair<int,int>
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, A, B, C;
int g[1010][1010];
bool visited[1010];


void dijkstra(vector<int> &dist,int x, int p, int q)
{
    dist[x] = 0;
    for(int i = 1; i <= n; i++)
    {
        int t = -1;
        for(int j = 1; j <= n; j++)
        {
            if(!visited[j] && (t == -1 || dist[j] < dist[t]))
                t = j;
        }
        visited[t] = true;
        for(int j = 1; j <= n; j++)
            dist[j] = min(dist[j], dist[t] + g[t][j] * p + q);
    }
}
void solve()
{
    cin >> n >> A >> B >> C;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
            cin >> g[i][j];
    }
    vector<int> dist1(n + 5, LLONG_MAX / 2), dist2(n + 5, LLONG_MAX / 2); 
    dijkstra(dist1, 1, A, 0);
    memset(visited, 0, sizeof visited);
    dijkstra(dist2, n, B, C);
    int ans = dist1[n];
    for (int i = 1; i <= n; i++)
    {
        ans = min(ans, dist1[i] + dist2[i]);
    }
    cout << ans << "\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

F - Sensor Optimization Dilemma

tag:动态规划(DP

题解:

这个题的数据范围较小,可以考虑双重甚至三重循环,大概能跑4*10^8,读题很容易想到背包,这题可以看成是有很多个多重背包,他只有两个物品,要装入n个背包。定义dp[i][j]为前i个物品中,消耗了第一个物品的数量为j,然后设他的值为第二个物品的最小数量,最后我们再遍历一遍求解即可。初始化dp[0][0] = 0;

// 加油昂!!!
// Problem: F - Sensor Optimization Dilemma
// Contest: AtCoder - KEYENCE Programming Contest 2023 Autumn(AtCoder Beginner Contest 325)
// URL: https://atcoder.jp/contests/abc325/tasks/abc325_f
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353, INF = 0x3f3f3f3f;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
int dp[110][1010];
void solve()
{
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    int l[2], c[2],k[2];
    for (int i = 0; i < 2; i++)
    {
        cin >> l[i] >> c[i] >> k[i];
    }
    memset(dp, 0x3f, sizeof dp);
    dp[0][0] = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= k[0]; j++)
        {
            for (int z = 0; z <= j; z++)
            {
                int res = (a[i] - l[0] * z + l[1] - 1) / l[1];
                res = max(res, 0ll);
                dp[i][j] = min(dp[i][j], dp[i - 1][j - z] + res);
            }
        }
    }
    int ans = LLONG_MAX / 2;
    for (int i = 0; i <= k[0]; i++)
    {
        if (dp[n][i] > k[1]) continue;
        ans = min(ans, i * c[0] + dp[n][i] * c[1]);
    }
    cout << (ans == LLONG_MAX / 2 ? -1 : ans) << "\n";
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nov-JovR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值