美团点评2019年秋招部分编程题汇总 解题报告 Apare_xzc

美团点评2019年秋招部分编程题汇总 企业独家授权

2020.8.7
Apare_xzc


在这里插入图片描述

网页链接:美团点评2019年秋招部分编程题汇总


1/7 [编程题] 图的遍历

给定一张包含N个点、N-1条边的无向连通图,节点从1到N编号,每条边的长度均为1。假设你从1号节点出发并打算遍历所有节点,那么总路程至少是多少?
在这里插入图片描述
在这里插入图片描述

分析:总边长的2倍减去根结点到某个叶子结点的最长路就是答案。dfs

#include <bits/stdc++.h>
using namespace std;
const int N = 100000+10; 
vector<int> edge[N];
int maxx;
void dfs(int x,int sum,int fa) {
	int len = edge[x].size();
	if(len==1&&edge[x][0]==fa) {
		maxx = max(maxx,sum);
		return;
	}
	for(int i=0;i<len;++i) {
		int to = edge[x][i];
		if(to!=fa) dfs(to,sum+1,x); 
	}
}
int main(void) {
	int n;
	cin>>n;
	int u,v;
	for(int i=1;i<n;++i) {
		scanf("%d%d",&u,&v);
		edge[u].push_back(v);
		edge[v].push_back(u);
	} 
	int ans = n*2-2;
	dfs(1,0,0);
	ans -= maxx;
	cout<<ans<<endl;
	return 0;
} 

2/7 [编程题] 最长全1串

给你一个01字符串,定义答案=该串中最长的连续1的长度,现在你有至多K次机会,每次机会可以将串中的某个0改成1,现在问最大的可能答案
在这里插入图片描述
在这里插入图片描述

分析:乍一看是二分答案,想一想直接尺取即可。

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
int a[N],n,k;
//bool check(int mid) {
//	int left = 
//}
int main(void) {
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;++i)
		scanf("%d",a+i);
	int left=1,right=1;
	int ans = 0;
	int cnt0 = 0;
	while(right<=n) {
		if(a[right]==0) ++cnt0;
		right++;
		while(cnt0>k) {
			if(a[left]==0) --cnt0;
			++left;
		}
		ans = max(ans,right-left);
	}	
	cout<<ans<<endl;
		
		
//	int left = 0,right = n+1,mid;
//	while(right-left>1) { //[)
//		mid = (left+right)>>1;
//		if(check(mid)) left = mid;
//		else right = mid;
//	} 
	
	return 0;
} 

3/7 [编程题] 外卖满减

你打开了美了么外卖,选择了一家店,你手里有一张满X元减10元的券,店里总共有n种菜,第i种菜一份需要A_i元,因为你不想吃太多份同一种菜,所以每种菜你最多只能点一份,现在问你最少需要选择多少元的商品才能使用这张券。
在这里插入图片描述

分析:01背包。

dp[i][j]代表前i个恰好凑够j元需要的最少钱数。
发现如果能凑够,那么dp[i][j]就是j,我们不用管,因为有的钱我们凑不出来。
因为是下好凑出来,所以没物品时
最后找dp[n][x]到dp[n][sum]这个区间能凑出来的最小值即可。

#include <bits/stdc++.h>
using namespace std;
const int N = 103;
int a[N];
int dp[10000+100];
int main(void) {
	int n,cap;
	scanf("%d%d",&n,&cap);
	int sum = 0;
	for(int i=1;i<=n;++i) scanf("%d",a+i),sum+=a[i];
	memset(dp,0x3f,sizeof(dp));
	dp[0] = 0;
	for(int i=1;i<=n;++i) {
		for(int j=sum;j>=a[i];--j)
			dp[j] = min(dp[j],dp[j-a[i]]+a[i]);
	}
	int res = dp[cap];
	for(int i=cap+1;i<=sum;++i)
		res = min(res,dp[i]);
	cout<<res<<endl;
	
	return 0;
} 

4/7 [编程题]种花

公园里有N个花园,初始时每个花园里都没有种花,园丁将花园从1到N编号并计划在编号为i的花园里恰好种A_i朵花,他每天会选择一个区间[L,R](1≤L≤R≤N)并在编号为L到R的花园里各种一朵花,那么园丁至少要花多少天才能完成计划?
在这里插入图片描述

分析

如果按题意模拟,找到区间最小值,区间都减去这个最小值,然后分成若干段,分段向下递归,这样复杂度过高。
给出一种贪心的伪代码:

ans = 0
for(int i=2;i<=n;++i)
	ans += max(0,a[i-1]-a[i])
ans += a[n]
return ans
#include <bits/stdc++.h>
using namespace std;
const int N = 100000+10;
int a[N];
int main(void) {
	int n;cin>>n;
	for(int i=1;i<=n;++i)
		scanf("%d",a+i);
	int ans = 0;
	for(int i=2;i<=n;++i)
		ans += max(0,a[i-1]-a[i]);
	ans += a[n];
	cout<<ans<<endl;
	
	return 0;
} 	

5/7 [编程题] 考试策略

小明同学在参加一场考试,考试时间2个小时。试卷上一共有n道题目,小明要在规定时间内,完成一定数量的题目。 考试中不限制试题作答顺序,对于 i 第道题目,小明有三种不同的策略可以选择: (1)直接跳过这道题目,不花费时间,本题得0分。

(2)只做一部分题目,花费pi分钟的时间,本题可以得到ai分。 (3)做完整个题目,花费qi分钟的时间,本题可以得到bi分。

在这里插入图片描述
在这里插入图片描述

分析: 01背包

#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int p[N],a[N],q[N],b[N];
int dp[N][130]; 
int main(void) {
	int n;
	cin>>n;
	for(int i=1;i<=n;++i)
		scanf("%d%d%d%d",p+i,a+i,q+i,b+i);
	for(int i=1;i<=n;++i) {
		for(int j=1;j<=120;++j) {
			dp[i][j] = dp[i-1][j];//这道题没做
			if(j>=p[i]) dp[i][j] = max(dp[i][j],dp[i-1][j-p[i]]+a[i]);
			if(j>=q[i]) dp[i][j] = max(dp[i][j],dp[i-1][j-q[i]]+b[i]);
		}
	}
	cout<<dp[n][120]<<endl;
	return 0;	
} 

6/7 [编程题] 路由器

一条直线上等距离放置了n台路由器。路由器自左向右从1到n编号。第i台路由器到第j台路由器的距离为| i-j |。 每台路由器都有自己的信号强度,第i台路由器的信号强度为ai。所有与第i台路由器距离不超过ai的路由器可以收到第i台路由器的信号(注意,每台路由器都能收到自己的信号)。问一共有多少台路由器可以收到至少k台不同路由器的信号。
在这里插入图片描述
在这里插入图片描述

分析:差分解决多次区间更新

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+100;
typedef long long LL;
LL a[N],b[N]; //a[]差分数组 
void add(int L,int R,LL add) {
	a[L]+=add;
	a[R+1]-=add;
}
int main(void) {
	int n,k,x;
	cin>>n>>k;
	for(int i=1;i<=n;++i) {
		scanf("%d",&x);
		int left = i-x;
		int right = i+x;
		add(max(1,left),min(right,n),1);
	}
	int ans = 0;
	for(int i=1;i<=n;++i) {
		b[i] = b[i-1]+a[i];
		if(b[i]>=k) ++ans; 
	}	
	cout<<ans<<endl;
		
	return 0;	
} 

第7题没写…


2020.8.7 22:35

猜你喜欢

转载自blog.csdn.net/qq_40531479/article/details/107870855