目录
E - Our clients, please wait a moment
F - Sensor Optimization Dilemma
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;
}