AcWing第35场周赛

第35场周赛

P4212. 字符串比较

先全部变为小写(-32),再依次比较

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main(){
	string a,b;
	cin>>a>>b;
	for(int i=0;i<a.length();i++){
		int x=a[i]-'0';
		int y=b[i]-'0';
		if(x>=49) x-=32;
		if(y>=49) y-=32;
		if(x>y){
			printf("1");
			return 0;
		}
		if(x<y){
			printf("-1");
			return 0;
		}
	}
	printf("0");	
	return 0;
}

P4213. 最小结果

可以发现总方案数很少,为 C 4 2 ⋅ C 3 2 ⋅ C 2 2 = 18 C_4^2\cdot C_3^2\cdot C_2^2=18 C42C32C22=18种,直接dfs即可
递归搜索树
搜索时按照前序遍历搜,用vector存,可支持变长,选完任意两个数后,每次新开一个vector,添加剩余的数以及这两个数计算的结果

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
LL ans=1e18;
char op[3];
void dfs(vector<LL> v,int u){//当前用到了第u个操作符
	if(v.size()==1) ans=min(ans,v[0]);
	else{
		for(int i=0;i<v.size();i++){
			for(int j=i+1;j<v.size();j++){
				vector<LL> t;
				for(int k=0;k<v.size();k++){
					if(k!=i&&k!=j){
						t.push_back(v[k]);//添加剩余的数
					}
				}
				//添加结果
				if(op[u]=='*') t.push_back(v[i]*v[j]);
				else t.push_back(v[i]+v[j]);
				dfs(t,u+1);
			}
		}
	}
}
int main(){
	vector<LL> v(4);
	for(int i=0;i<4;i++) scanf("%lld",&v[i]);
	for(int i=0;i<3;i++) scanf("%s",&op[i]);//因为有空格,建议直接用字符串
	dfs(v,0);
	printf("%lld",ans);
	return 0;
}

为什么不用恢复现场? 每次我们是新开了一个t数组来存储当前所有数,不管t数组怎么变,都不会影响到一开始的v数组;如果我们在一开始给v加个引用,每次直接在v上面进行操作,就需要恢复现场,如下图:
恢复现场

P4214. 三元组

三元组
正解为状态机dp,较麻烦,这里讲怎么枚举,如果用三重循环来枚举的话会超时,需要优化
考虑枚举j, S i S_i Si只要小于 S j S_j Sj即可,跟 S k S_k Sk没有关系, S k S_k Sk同理,所以i和k是相互独立的,我们只要分别求出 C i C_i Ci C k C_k Ck的最小值,然后三项相加即可
结论一般化:若要求f(x)+g(y)+h(z),如果三项独立,我们只要让三项分别取最值相加,如果不独立就需要一层一层枚举了

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=3010,INF=3e8+10;
int n;
int s[N],c[N];
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%d",&s[i]);
	for(int i=0;i<n;i++) scanf("%d",&c[i]);
	int res=INF;
	for(int j=0;j<n;j++){
		int left=INF;
		for(int i=0;i<j;i++){
			if(s[i]<s[j]) left=min(left,c[i]);
		}
		int right=INF;
		for(int k=j+1;k<n;k++){
			if(s[j]<s[k]) right=min(right,c[k]);
		}
		res=min(res,left+c[j]+right);
	}
	if(res==INF) printf("-1");
	else printf("%d",res);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值