华为2022批笔试题解

总结:正常难度的欢乐笔试

T1

  • 题目大意:给出 n n n个任务的失效时间和价值(失效后完成便无法获得价值),每分钟只能做一个任务,求出最大的价值和
  • 数据范围 n < = 1 e 6 n<=1e6 n<=1e6

反悔贪心模板题:
首先对于所有任务按照失效时间从小到大进行排序,使用一个集合s表示为当前所选的任务价值。扫一遍所有的任务,如果只能选择一个加入的话,就将当前任务加入集合中,同时将集合中最小的一个元素取出。代表着取消了价值最小的操作,换为现在这个操作,进行操作的同时计算贡献即可。

代码实现:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define maxn 1000005
#define ins insert
#define pb push_back
#define inf 1e9
using namespace std;

inline ll read()
{
	ll x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') x=(x<<1)+(x<<3)+c-'0',c=getchar();
	return w==1?x:-x;
}

multiset <ll> s;
multiset <ll>::iterator it;
struct node{ll s,w;}p[maxn];
ll n,ans;

inline bool cmp(node a,node b)
{
	if(a.s!=b.s) return a.s<b.s;
	return a.w>b.w;
}

int main()
{
	n=read(); rep(i,1,n) p[i].s=read(),p[i].w=read();
	sort(p+1,p+n+1,cmp); int nw=1;
	rep(i,1,n)
	{
		s.ins(p[nw].w); ans+=p[nw].w; nw++;
		while(p[nw].s==i)
		{
			s.ins(p[nw].w); ans+=p[nw].w; nw++;
			it=s.begin(); ans-=(*it); s.erase(it);
		}
		if(nw>n) break;
	}
	cout<<ans<<endl;
	return 0;
}

/*
7
1 6
1 7
3 2
3 1
2 4
2 5
6 1

15*/

T2

  • 题目大意:给出 n n n个节点, m m m条边的带权有向图,给出一个起点s,问是否能访问到所有点,能的话输出最长路径。
  • 数据范围 n < = 100 n<=100 n<=100

记忆化搜索模板题:
使用 d p [ u ] dp[u] dp[u]表示从u节点开始的最长路径,记忆化搜索即可,具体实现看代码大家就明白了…

代码实现:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define maxn 1000005
#define ins insert
#define pb push_back
#define inf 1e9
using namespace std;

inline int read()
{
	int x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') x=(x<<1)+(x<<3)+c-'0',c=getchar();
	return w==1?x:-x;
}

int n,m,s,vis[maxn],dfn[maxn],cnt;
ll dp[maxn];
struct node{int to,w;};
vector <node> mp[maxn];

inline ll dfs(int u)
{
	if(dp[u]) return dp[u];
	if(!dfn[u]) dfn[u]=1,cnt++;
	ll tmp=0;
	for(auto v:mp[u])
	{
		if(vis[v.to]) continue;
		vis[v.to]=1;
		tmp=max(tmp,dfs(v.to)+v.w);
		vis[v.to]=0;
	}
	return dp[u]=tmp;
}

int main()
{
	n=read(); m=read(); s=read(); //n点数 m边数 s为起点
	rep(i,1,m)
	{
		int u=read(),v=read(),w=read();
		mp[u].pb({v,w});
	}
	vis[s]=1; dfs(s);
	if(cnt==n) cout<<dp[s]<<endl; else puts("-1");
	return 0;
}


/*
4 3 1
1 2 15
1 3 7
3 4 9

16
*/

T3

  • 题目大意:在中国象棋中,给出大小为 n ∗ m n*m nm的棋盘,棋盘上有一些障碍点,以及一匹马在S处要到T点,给出中国象棋中跳马的规则,问至少需要多少步才能跳到T点
  • 数据范围 n , m < = 150 n,m<=150 n,m<=150

BFS模板题:
是每场笔试都会有的模拟题,考虑 d [ x ] [ y ] d[x][y] d[x][y]表示从S点到 ( x , y ) (x,y) (x,y)的最短路,然后BFS处理即可,具体实现见代码

代码实现:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define maxn 1000005
#define ins insert
#define pb push_back
#define inf 1e9
using namespace std;

inline int read()
{
	int x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') x=(x<<1)+(x<<3)+c-'0',c=getchar();
	return w==1?x:-x;
}

char mp[155][155];
int n,m,sx,sy,tx,ty,d[155][155];
struct node{int x,y;};
queue <node> q;

const int kx[8]={1,-1,1,-1,-2,-2,2,2};
const int ky[8]={-2,-2,2,2,1,-1,1,-1};

int main()
{
	n=read(); m=read(); rep(i,1,n) scanf("%s",mp[i]+1);
	rep(i,1,n) rep(j,1,m) d[i][j]=inf;
	rep(i,1,n) rep(j,1,m)
	{
		if(mp[i][j]=='H') sx=i,sy=j,d[i][j]=0,q.push({i,j});
		if(mp[i][j]=='T') tx=i,ty=j;
	}
	while(!q.empty())
	{
		auto u=q.front(); q.pop();
		rep(k,0,7)
		{
			int xx=u.x+kx[k],yy=u.y+ky[k];
			if(xx<=0||xx>n||yy<=0||yy>m||d[xx][yy]!=inf||mp[xx][yy]=='#') continue;
			if((k==0||k==1)&&mp[u.x][u.y-1]=='#') continue;
			if((k==2||k==3)&&mp[u.x][u.y+1]=='#') continue;
			if((k==4||k==5)&&mp[u.x-1][u.y]=='#') continue;
			if((k==6||k==7)&&mp[u.x+1][u.y]=='#') continue;
			d[xx][yy]=d[u.x][u.y]+1; q.push({xx,yy});
		}
	}
	if(d[tx][ty]==inf) puts("-1"); else cout<<d[tx][ty]<<endl;
	return 0;
}

/*
5 13
........H...#
........#....
.....#.......
.#...........
..........T#.

4
*/

END

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值