郑州大学2024年3月招新赛题解

1.两重二for循环+维护次大值

这里我就直接用map维护了,多了个logn复杂度还是可以的,下面是AC代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,a[1010];
map<int,int> mp;
int main(){
	cin>>n;
	int sum=0;
	map<int,int>::iterator it;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n-1;i++){
		mp.clear();
		mp[a[i]]=1;
		for(int j=i+1;j<=n;j++){
			mp[a[j]]=1;
			it=mp.end();
			it--;
			it--;
			sum+=(it->first);
		}
		mp.erase(a[i]);
	}	
	cout<<sum;
} 

2.二分查找+迪杰斯特拉:

显然,我们考虑每一次遍历时的最大体力值a,若a可以,那么比a大的肯定也可,满足单调性。

我们在每次二分时按照体力建图跑个迪杰斯特拉即可,下面是AC代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,m,h,w,cnt,head[10101],st,ed,a[10101],max1,min1,ss;
bool vis[10010];
struct node{
	int dian,next,zhi;
}edge[40006];
int xx[20006],yy[20006],ww[20006];
int dis[10101];
void merge(int u,int v,int bb){
	edge[++cnt].dian=v;
	edge[cnt].next=head[u];
	edge[cnt].zhi=bb;
	head[u]=cnt;
}
struct ty{
	int dian,dis1;
	bool operator<(const ty &a) const{
	 return dis1>a.dis1;
	}
};
priority_queue<ty> q;
int dij(int s,int t){
	q.push({s,0});
	while(!q.empty()){
		ty ck=q.top();
		q.pop();
		if(vis[ck.dian]) continue;
		vis[ck.dian]=1;
		for(int i=head[ck.dian];i!=-1;i=edge[i].next){
			int i1=edge[i].dian;
			if(vis[i1]) continue;
			if(dis[i1]>dis[ck.dian]+edge[i].zhi){
				dis[i1]=dis[ck.dian]+edge[i].zhi;
				q.push({i1,dis[i1]});
			}
		}
	}
	if(dis[t]>=1e8) return -1;
	else return dis[t];
}
bool check(int mid){
	cnt=0;
	memset(head,-1,sizeof(head));
	memset(edge,0,sizeof(edge));
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=m;i++){
		if(a[xx[i]]>mid||a[yy[i]]>mid) continue;
		merge(xx[i],yy[i],ww[i]);
		merge(yy[i],xx[i],ww[i]);
	}
	memset(dis,0x7f7f7f7f,sizeof(dis));
	dis[st]=0;
	int yy=dij(st,ed);
	if(yy==-1||yy>h) return 0;
	else return 1;
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m>>st>>ed>>h;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		max1=max(max1,a[i]);
		min1=min(min1,a[i]);
	}
	min1=max(a[st],min1);
	min1=max(a[ed],min1);
	for(int i=1;i<=m;i++) cin>>xx[i]>>yy[i]>>ww[i];
	int i=min1,j=max1;
	int f=0;
	while(i<j){
		int mid=(i+j)/2;
		if(check(mid)){
			f=1;
			 j=mid;
		}
		else i=mid+1;
	}
	if(f==0) cout<<-1;
	else cout<<i;
}

3.模拟:

按照字符串模拟即可,下面是AC代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,m,sx,sy,l,dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
char a[5100][5100];
string s;
struct node{
	int x,y;
}tr[2][40];
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++) cin>>a[i][j];
	}
	cin>>sx>>sy>>l>>s;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char c=a[i][j];
			if(c>='A'&&c<='Z'){
				int qq=c-'A';
				if(tr[0][qq].x==0&&tr[0][qq].y==0){
					tr[0][qq].x=i;
					tr[0][qq].y=j;
				}
				else{
					tr[1][qq].x=i;
					tr[1][qq].y=j;
				}
			}
		}
	}
	for(int i=0;i<=s.length()-1;i++){
		int x=sx,y=sy;
		if(s[i]=='L') y--;
		if(s[i]=='R') y++;
		if(s[i]=='U') x--;
		if(s[i]=='D') x++;
		if(a[x][y]=='#') continue;
		if(x<1||y<1||x>n||y>m) continue;
		if(a[x][y]>='A'&&a[x][y]<='Z'){
			int ww=a[x][y]-'A';
			if(tr[0][ww].x==x&&tr[0][ww].y==y){
					sx=tr[1][ww].x;
					sy=tr[1][ww].y;
			}
			else{
				sx=tr[0][ww].x;
				sy=tr[0][ww].y;
			}
		}	
		else{
			sx=x;
			sy=y;
		}
	}
	cout<<sx<<" "<<sy;
}

4.BFS:

发现这道跟洛谷的一道类似,这里就懒一下放个以前洛谷上写的吧:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,m,vis[400][400],stx,sty,edx,edy;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct pos{
	int x,y,t;
};
struct node{
	int x,y;
}tr[2][40];
queue<pos> q;
char c,a[400][400];
bool check(int x,int y){
	if(x<1||x>n||y<1||y>m||vis[x][y]==1||a[x][y]=='#') return 0;
	return 1;
}
void bfs(){
	q.push({stx,sty,0});
	vis[stx][sty]=1;
	while(!q.empty()){
		pos ck=q.front();
		q.pop();
		int xx=ck.x,yy=ck.y;
		if(xx==edx&&yy==edy){
			cout<<ck.t;
			return;
		}
		for(int i=0;i<4;i++){
			int xxx=xx+dir[i][0];
			int yyy=yy+dir[i][1];
			if(check(xxx,yyy)==0) continue;
			if(a[xxx][yyy]>'Z'||a[xxx][yyy]<'A'){
				vis[xxx][yyy]=1;
				q.push({xxx,yyy,ck.t+1});
			}
			else{
				int ww=a[xxx][yyy]-'A';
				if(tr[0][ww].x==xxx&&tr[0][ww].y==yyy){
					q.push({tr[1][ww].x,tr[1][ww].y,ck.t+1});
				}
				else q.push({tr[0][ww].x,tr[0][ww].y,ck.t+1});
			}
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>c;
			a[i][j]=c;
			if(c=='@'){
				stx=i;
				sty=j;
			}
			if(c=='='){
				edx=i;
				edy=j;
			}
			if(c>='A'&&c<='Z'){
				int qq=c-'A';
				if(tr[0][qq].x==0&&tr[0][qq].y==0){
					tr[0][qq].x=i;
					tr[0][qq].y=j;
				}
				else{
					tr[1][qq].x=i;
					tr[1][qq].y=j;
				}
			}
		}
	}
	bfs();
}

5.签到题(别被题面吓了)

取字符串最后一位即可。

6.斐波那契数列:

来个矩阵快速幂~~~:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int m,n,mod=1e9+7;
struct node{
	int m[100][100];
}ans,res;
node mul(node a,node b){
	node tmp;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			tmp.m[i][j]=0;
		}
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			for(int k=0;k<n;k++){
				tmp.m[i][j]=(tmp.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
			}
		}
	}
	return tmp;
}
void quickpower(int m,int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(i==j) ans.m[i][j]=1;
			else ans.m[i][j]=0;
		}
	}
	while(m){
		if(m&1) ans=mul(ans,res);
		res=mul(res,res);
		m=m>>1; 
	}
}
signed main(){
	cin>>m;
	m-=2;
	n=2;
	res.m[0][0]=0;
	res.m[1][0]=1;
	res.m[1][1]=1;
	res.m[0][1]=1;
	if(m<0) cout<<1;
	else {quickpower(m,n);
	cout<<(ans.m[1][0]+ans.m[1][1])%mod;}
}

7.(不会QAQ...)

8.DP:

我们令dp[i][j][k](k=0/1)表示取到第i个字符,前面转折次数<=j,最后一段是升/降的最长长度。

对于dp[i][j][1],我们遍历1--i-1作为第i个字符的前一个字符,如果比a[i]大,那么就可以直接接在dp[h][j][1]的后面,长度+1,否则可以多加一个转折dp[h][j-1][0]然后+1.对于dp[i][j][0]同理。

下面是AC代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,k,dp[1010][1010][2],ans,a[1010];
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++){
		for(int j=0;j<=k;j++){
			dp[i][j][0]=1;
			dp[i][j][1]=1;
			for(int h=1;h<i;h++){
				if(a[h]>a[i]){
					dp[i][j][0]=max(dp[i][j][0],dp[h][j][0]+1);
					if(j>=1) dp[i][j][0]=max(dp[i][j][0],dp[h][j-1][1]+1);
				}
				if(a[h]<a[i]){
					dp[i][j][1]=max(dp[i][j][1],dp[h][j][1]+1);
					if(j>=1) dp[i][j][1]=max(dp[i][j][1],dp[h][j-1][0]+1);
				}
			}
			ans=max(ans,dp[i][j][0]);
			ans=max(ans,dp[i][j][1]);
		}
	}
	cout<<ans;
}

9.模拟:

直接按题目意思模拟即可。

10.贪心:

自己写几个找找规律,可以发现删序列出现递减的前一个数字即可,下面是AC代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
char num[1000100],x;
bool a[1000100];
int n;
int main(){
	cin>>n;
	for(int i=0;i<=n-1;i++){
		scanf(" %c",&x);
		num[i]=x;}
	if(n==1) cout<<0;
	else if(n==2&&num[1]=='0') cout<<0;
	else{

		int f=0;
		for(int i=0;i<n-1;i++){
			if(num[i]>num[i+1]&&f==0){
				f=1;
				a[i]=1;
				continue;
			}
			
		}
		if(f==0) a[n-1]=1;
		int kkk=0,cnt=0;
		for(int i=0;i<=n-1;i++){
			if(a[i]==1) continue;
			if(kkk==0&&num[i]=='0') continue;
			kkk=1;
			cout<<num[i];
			cnt++;
		}
		if(cnt==0) cout<<0;	
	
	}
}

11.数学

直接BFS就TLE了,我们发现我们按照1,3,6,10.。。取下去,若第一个数==答案或者-2>=答案,我们都可以通过吧一个数改成-1来实现,否则次数+1即可。

下面是AC代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,k,t;
void solve(){
	int sum=0,res=0;
	for(int i=1;i<=2000;i++){
		sum+=i;
		if(sum==n||sum-1>n){
			res=i;
			break;
		}
	}
	cout<<res;
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		solve();
		cout<<endl;
	}
}

12.前缀和+二分:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,q,a[1000100];
long long sum;
long long ss[1000100];
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>q;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) ss[i]=ss[i-1]+a[i];
	for(int i=1;i<=q;i++){
		cin>>sum;
		int j=lower_bound(ss+1,ss+n+1,sum)-ss;
		if(j==n+1) cout<<-1;
		else printf("%d\n",j);
	}	
}
相关推荐
ragnwang18 分钟前
C++ Eigen常见的高级用法 [学习笔记]
c++·笔记·学习
yuanManGan41 分钟前
数据结构漫游记:静态链表的实现(CPP)
数据结构·链表
火星机器人life2 小时前
基于ceres优化的3d激光雷达开源算法
算法·3d
虽千万人 吾往矣2 小时前
golang LeetCode 热题 100(动态规划)-更新中
算法·leetcode·动态规划
arnold663 小时前
华为OD E卷(100分)34-转盘寿司
算法·华为od
ZZTC3 小时前
Floyd算法及其扩展应用
算法
lqqjuly3 小时前
特殊的“Undefined Reference xxx“编译错误
c语言·c++
lshzdq3 小时前
【机器人】机械臂轨迹和转矩控制对比
人工智能·算法·机器人
冰红茶兑滴水4 小时前
云备份项目--工具类编写
linux·c++
刘好念4 小时前
[OpenGL]使用 Compute Shader 实现矩阵点乘
c++·计算机图形学·opengl·glsl