2024-10-07-ABC374

A - Takahashi san 2

输入一个字符串,判断是不是以"san"结尾。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	string s;
	cin>>s;
	if(s.substr(s.size()-3)=="san")
		puts("Yes");
	else
		puts("No");
	return 0;
}

B - Unvarnished Report

给定两个字符串S和T,如果两个字符串完全一样输出0,不一样的话输出第一个不同的字母的位置。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	string s,t;
	cin>>s>>t;
	if(s==t) puts("0");
	else {
		int n=s.size(),m=t.size(),ans=min(n,m);//如果是长度不同那么ans就是短的长度+1
		for(int i=0;i<min(n,m);i++)
		{
			if(s[i]!=t[i])
			{
				ans=i;
				break;
			}
		}
		cout<<ans+1;//要求下标输出从1开始
	}
	return 0;
}

C - Separated Lunch

给定一个数组,把这个数组分成两组,设一组的和为A,另一组的和为B,求在所有的拆分方案下,max(A,B)的最小值。

N不超过20,01穷举即可。

#include<bits/stdc++.h>
using namespace std;
int n;
int a[25], sum;
int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
		sum += a[i];
	}
	int ans = 2e9+7;
	for (int msk = 0; msk < (1 << n); msk++) {
		int tmp = 0;
		for (int i = 0; i < n; i++)
			if (msk & (1 << i))
				tmp += a[i];
		ans = min(ans, max(tmp, sum - tmp));
	}
	cout << ans;
	return 0;
}

D - Laser Marking

二维平面,给定n个线段,用激光打印机打印。

激光移动速率为s,打印时的速率为 t。

规定打印顺序,使得耗时最短。初始激光位于(0,0)。

3 2 1
1 3 2 1
0 2 0 0
3 0 2 0

image-20241007195337893

线段不超过六个,所以可以全排列每条线段走的顺序,并枚举每一条线段是从两个端点的哪个端点开始。

当然用dfs暴力地走每一条线也可以。

#include <bits/stdc++.h>
using namespace std;
const int maxn=10;
int A[10],B[10],C[10],D[10],N,S,T;
bool vis[maxn];
double ans=INFINITY;
double calc(double x,double y)
{
	return sqrt(x*x+y*y);
}
void dfs(int x, int y, double sum, int c) {//当前位置,当前总和,当前到第几条线段
	if (c == N) {
		ans = min(ans, sum);
		return;
	}
	for (int i = 0; i < N; i++) {
		if (vis[i]) {
			continue;
		}
		double d1 = calc(A[i] - x, B[i] - y);
		double d2 = calc(C[i] - x, D[i] - y);
		double d0 = calc(A[i] - C[i], B[i] - D[i]);
		vis[i] = true;
		dfs(C[i], D[i], sum + d1 / S + d0 / T, c + 1);//从AB->CD
		dfs(A[i], B[i], sum + d2 / S + d0 / T, c + 1);//从CD->AB
		vis[i] = false;
	}
};
int main() {
	cin >> N;
	cin >> S >> T;
	for (int i = 0; i < N; i++)
		cin >> A[i] >> B[i] >> C[i] >> D[i];
	dfs(0, 0,0.0,0);
	cout << fixed << setprecision(20) << ans << "\n";
	return 0;
}

E - Sensor Optimization Dilemma 2

制作产品,有n道工序。

每道工序有两种设备,单价pi和qi,分别可做ai和bi个产品。

最终的生产效率是所有工序的产品数量的最小值。

现有x元,问生产效率的最大值。

image-20241007205141949

生产效率低容易达成,越高越难达成,他求的是最大的能达成的分界线,所以我们可以二分答案。

二分生产效率t,那么条件就是check每一道工序的产品数量都得大于等于t,并且总价不超过x。

为了达成这个条件,其实就是求每一道工序产品数量大于等于t时最少要花多少钱,然后把所有的价格加在一起和x比较。一般来说我们会全选择单价较低的机器,但是这有可能不是最优解。

比如:两块三个产品,三块四个产品,现在要7个产品,那么最优解是两种机器各买一个,而不是全买单价更低的第一种机器。

那么策略应该是先全买单价更低的机器,然后试图看买几个单价高的机器去替换单价低的机器能不能使答案更好。

那最多会买多少个高单价的机器呢,题目中A和B不超过100,那么也就说明不会超过100个,比如刚才的(两块三个产品,三块四个产品),A=3,B=4,那么对于LCM(A,B),两者的最小公倍数,也就是12个产品时,一定是单价小的来得更好,也就为什么买的多了一定是单价小的更好,这个具体的分界线就是最小公倍数。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 105;
int A[maxn], B[maxn], P[maxn], Q[maxn];
int N,X;
bool check(int u) {
	ll ans = 0;
	for (int i = 0; i < N; i++) {
		ll res = 1E18;
		for (int j = 0; j <= 100; j++) {//枚举买多少个单价高的
			ll 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 main() {
	cin >> N >> X;
	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]) {//调整为A是单价高的,B是单价低的
			swap(A[i], B[i]);
			swap(P[i], Q[i]);
		}
	}
	int lo = 0, hi = 1E9;
	while (lo < hi) {
		int x = (lo + hi + 1) / 2;
		if (check(x)) {
			lo = x;
		} else {
			hi = x - 1;
		}
	}
	cout << lo << "\n";
	return 0;
}
posted @ 2024-11-30 23:27  ~清渠~  阅读(1)  评论(0编辑  收藏  举报