A - Takahashi san 2
题意:输入一个字符串 S,如果它以 san 结尾,则输出 Yes,否则输出 No。
思路:模拟后三位即可
string s;
cin >> s;
if(s.substr(sz(s)-3,3) == "san")cout <<"Yes\n";
else cout <<"No\n";
return 0;
B - Unvarnished Report
题意:给定两个字符串 s 和 s1,请求出两个字符串中的字符第一次不相同的位置是哪里。如果两个字符串完全相同,请输出 0。
思路:模拟即可
string q , w;
cin >> q >> w;
if(q == w)cout <<"0\n";
else{
if(sz(q) > sz(w))swap(q , w);
for(int i = 0;i<sz(q);i++){
if(q[i]!=w[i]){
cout << i + 1<< endl;
return 0;
}
}
cout <<sz(q) + 1 << endl;
}
C - Separated Lunch
题意:
总部有 N 个部门,第 i 个部门 (1≤i≤N) 的人数为 Ki 。
将每个部门分配到 A 组或 B 组,让每个组里面的所有人在同一时间午休,并确保 A 组和 B 组的午休时间不重叠,求同一时间午休的最大人数的最小值。
换句话说,求分配给 A 组的部门总人数和分配给 B 组的部门总人数中较大者的最小值。
思路:观察到N < 20,枚举所有情况DFS即可
// Code Start Here
int n;
cin >> n;
vector<int> a(n);
for(int i = 0;i<n;i++)cin >> a[i];
int ans = INF;
int sum = 0;
for(int i = 0;i<n;i++)sum +=a[i];
auto dfs = [&](auto dfs,int deep,int now){
if(deep == n){
ans = min(ans,max(now,sum - now));
return;
}
dfs(dfs,deep+1,now + a[deep]);
dfs(dfs,deep+1,now);
};
dfs(dfs,0,0);
cout << ans << endl;
return 0;
题意:
有一台打印机,它可以通过发射激光束在 xy 平面上打印线段。
-
最开始时,激光位于坐标 (0, 0)。
-
要打印一条线段时,打印机必须遵循以下流程:
- 首先,将激光从当前位置移动到要打印线段的一个端点。
- 可以任选一个端点移过去准备打印。
- 然后,发射激光,打印这条线段。将激光从一个端点沿直线移动到另一个端点。
- 在这个过程中不允许关闭激光。
- 首先,将激光从当前位置移动到要打印线段的一个端点。
-
不发射激光时,可以以每秒 S 个单位的速度向任何方向移动激光的位置。
-
发射激光时,可以以每秒 T 个单位的速度沿着线段移动激光的位置。
-
除移动激光的位置外,其它所有操作所需的时间都忽略。
高桥希望用这台打印机打印 N 条线段。 第 i 个线段连接坐标 (Ai, Bi) 和 (Ci, Di)。 请注意,有几条线段可能会重叠,但每次都必须打印所有线段的重叠部分。
当他以最佳方式操作印刷机时,完成所有线段的印刷至少需要多少秒?
思路:一个比较麻烦的模拟题,注意到需要枚举线段的先后顺序,然后每个线段有两种画的方式,时间复杂度很好,但是观察到最多只有六条线段,所以直接枚举+DFS即可
// Code Start Here
int N,S,T;
cin >> N >> S >> T;
vector<int> A(N), B(N), C(N), D(N);
for (int i = 0; i < N; i++) {
cin >> A[i] >> B[i] >> C[i] >> D[i];
}
double ans = INF;
vector<bool> vis(N);
auto dfs = [&](auto &self, int x, int y, double sum = 0.0, int c = 0) {
if (c == N) {
ans = min(ans, sum);
return;
}
for (int i = 0; i < N; i++) {
if (vis[i]) {
continue;
}
//hypot函数返回原点到给定坐标的欧几里得距离
double d1 = hypot(A[i] - x, B[i] - y);
double d2 = hypot(C[i] - x, D[i] - y);
double d0 = hypot(A[i] - C[i], B[i] - D[i]);
vis[i] = true;
self(self, C[i], D[i], sum + d1 / S + d0 / T, c + 1);
self(self, A[i], B[i], sum + d2 / S + d0 / T, c + 1);
vis[i] = false;
}
};
dfs(dfs,0,0,0);
cout << point(20) << ans <<endl;
dfs(dfs, 0, 0);
cout << fixed << setprecision(20) << ans << endl;
E - Sensor Optimization Dilemma 2
题意:
我们有 N 个工序,每个工序需要达到至少 u的产能。对于工序 i:有两种机器可供选择:
机器 Si:每台每天可处理 Ai 个产品,价格为 Pi;
机器 Ti:每台每天可处理 Bi 个产品,价格为 Qi。
可以任意购买这两种机器的任意数量,目标是让每个工序的总产能达到 u(即总产能为各工序产能的最小值),并且全局花费不超过预算 X 日元。
我们的目标是求出在预算 X 内,能够达到的最大产能 u。
思路:
由于 u 的取值范围很大(最高可达 10^9),我们采用二分搜索确定最大的可行 u。对于每个候选的 u,需要判断是否能在预算内实现每个工序的产能不少于 u。
对于工序 i,我们需要用两种机器的组合来达到至少 u 的产能。令购买x 台 Si 和 y 台Ti 后,总产能为
x*Ai+y*Bi≥u,
总花费为
x*Pi+y*Qi.
所以模型可以转化为:在满足产能要求的前提下,如何组合购买 Si 和 Ti 使得花费最小?
为了方便后续讨论,代码先对每个工序判断两种机器的性价比:
- 机器 Si 的性价比:Ai/Pi
- 机器 Ti 的性价比:Bi/Qi
如果发现 Ai/Pi <Bi/Qi ,即 Ai×Qi<Bi×Pi,则交换两种机器的信息。这样交换后,我们保证机器 Si 的单位产能成本不高于机器 Ti(即 S 更“划算”)。通常我们希望尽可能多地使用更划算的 S,但有时因为 S 的产能增量较大,可能导致购买 S 时“过量”,此时适当使用 T 来填补余缺可能会更便宜。
然后很明显的,我们可以暴力枚举 T 的台数,二分搜索求最大u即可
// Code Start Here
int N, X;
cin >> N >> X;
vector<int> A(N), B(N), P(N), Q(N);
for (int i = 0; i < N; i++) {
cin >> A[i] >> P[i] >> B[i] >> Q[i];
if (A[i] * Q[i] < B[i] * P[i]) {
swap(A[i], B[i]);
swap(P[i], Q[i]);
}
}
auto check = [&](int u) {
int ans = 0;
for (int i = 0; i < N; i++) {
int res = 1E18;
for (int j = 0; j <= 100; j++) {
int v = j * Q[i];
int need = u - j * B[i];
if (need > 0) {
v += 1LL * (need + A[i] - 1) / A[i] * P[i];
}
res = min(res, v);
}
ans += res;
}
return ans <= X;
};
int l = 0, r = 1E9;
while (l < r) {
int x = l + r + 1 >> 1;
if (check(x)) {
l = x;
} else {
r = x - 1;
}
}
cout << l <<endl;
return 0;
603

被折叠的 条评论
为什么被折叠?



