美团点评秋招编程题

来源:互联网 发布:晴天软件注册码 编辑:程序博客网 时间:2024/04/28 15:55

[编程题] 大富翁游戏

时间限制:1秒
空间限制:32768K
大富翁游戏,玩家根据骰子的点数决定走的步数,即骰子点数为1时可以走一步,点数为2时可以走两步,点数为n时可以走n步。求玩家走到第n步(n<=骰子最大点数且是方法的唯一入参)时,总共有多少种投骰子的方法。
输入描述:
输入包括一个整数n,(1 ≤ n ≤ 6)
输出描述:
输出一个整数,表示投骰子的方法
输入例子1:
6
输出例子1:
32

解析:

f(n)表示走到n的方案数量。每次走的步数为[1-6]。
第一次可以走1步,则剩下n-1未走, 方案数为f(n-1);
第一次也可以走2步,则剩下n-2未走,方案数为f(n-2);

第一次走6步,则剩下n-6未走,方案数为f(n-6);
因此,走到n的方案有:
f(n) = f(n-1)+f(n-2)+f(n-3)+f(n-4)+f(n-5)+f(n-6)。
其中,f(0)=1,f(1)=1

c++代码实现:

#include <iostream>using namespace std;int main(){    int n;    cin>>n;    int fn[7]={1,1,0,0,0,0,0};    for(int i=2; i<=n; i++){        for(int j=1; j<=i; j++){            fn[i] += fn[i-j];        }    }    cout<<fn[n];    return 0;}

[编程题] 拼凑钱币

时间限制:1秒
空间限制:32768K
给你六种面额 1、5、10、20、50、100 元的纸币,假设每种币值的数量都足够多,编写程序求组成N元(N为0~10000的非负整数)的不同组合的个数。
输入描述:
输入包括一个整数n(1 ≤ n ≤ 10000)
输出描述:
输出一个整数,表示不同的组合方案数
输入例子1:
1
输出例子1:
1

解析:

类似于背包问题,只是每种纸币可以选取多个。即对于每个面额为coin[i]纸币,选X[i]个,使得sum(coin[i]*x[i]) = n元。
我们可以假设每种面额的纸币只选一次,从1元纸币开始,则总共只需要选择6次,每次选择对应的面额的纸币。
用dp[i][j]代表选择i次凑成j元的不同组合个数,结果即为dp[6][n]。
dp[0][j] = 0, 选择0次不可能凑成j元;
dp[i][0] = 1, 选择i次凑成0元的方案只有一个,那就是每种面额纸币的数量都为0。
对于dp[i][j],举个例子dp[3][10]表示选择i次凑成10元的方案数,第三次可以选择0或1张10元的纸币,这意味着前2次选择后,已经凑成了10元或者0元。
即dp[3][10]=dp[2][10]+dp[2][0]。
因此,对于dp[i][j],第i次选可以选择0~j/coin[i]张面额为coin[i]的纸币,即前i-1次选择后,已经有了j-k*coin[i]的钱。
dp[i][j] = sum(dp[i-1][j-k*coin[i]]), k = 0~j/coin[i]

C++代码实现:

#include <iostream>using namespace std;long long dp[7][10001]={0};int coin[6] = {1,5,10,20,50,100};long long combineN(int n){    int i,j,k,m;    for( i=0; i<=n; i++)        dp[0][i] = 0;    for( i=0; i<=6; i++)        dp[i][0] = 1;   //凑0元的方案就只有一种,那就是都不选    for(int i=1; i<=6; i++){        for( j=1; j<=n; j++){            m = j/coin[i-1];            for( k=0; k<=m; k++)                dp[i][j] += dp[i-1][j-k*coin[i-1]];        }    }    return dp[6][n];}int main(){    int n;    cin>>n;    cout<<combineN(n);    return 0;}

[编程题] 最大矩形面积

时间限制:1秒
空间限制:32768K
给定一组非负整数组成的数组h,代表一组柱状图的高度,其中每个柱子的宽度都为1。 在这组柱状图中找到能组成的最大矩形的面积(如图所示)。 入参h为一个整型数组,代表每个柱子的高度,返回面积的值。
这里写图片描述
输入描述:
输入包括两行,第一行包含一个整数n(1 ≤ n ≤ 10000)
第二行包括n个整数,表示h数组中的每个值,h_i(1 ≤ h_i ≤ 1,000,000)
输出描述:
输出一个整数,表示最大的矩阵面积。
输入例子1:
6
2 1 5 6 2 3
输出例子1:
10

解析:

(1)方法一:穷举法。对于每个柱子,穷举所有的左边界,记录最大面积。这样穷举时间复杂度为O(n^2)。因此,必须剪枝,比如找到合适的右边界。我们发现当height[k] >= height[k-1]时,无论左边界取什么值,选择height[k]作为右边界总会比选择height[k-1]所形成的面积大。因此,在选择右边界时,我们首先找到一个height[k] < height[k-1]的k, 然后取k-1作为右边界, 然后穷举所有的左边界,找到最大面积。
(2)方法二:穷举法还有一个思路。对于每个柱子i,定义left[i]和right[i],分别表示柱子i能延伸的左边界,和柱子i能延伸的右边界,然后计算该矩形的面积。柱子i的左边界为离i最近的j,且height[j] < height[i],左边界即为j+1。柱子的右边界为离i最近的j,且height[j] < height[i],右边界即为j-1。时间复杂度为O(n)。
(3)方法三:使用一个栈的O(n)解法,栈内存储的是高度递增的柱子下标。对于每一个柱子i,分两种情况: 1:当栈空或者当前柱子i高度大于栈顶下标所指示柱子的高度时,当前下标入栈。否则,2:当前栈顶出栈,并且用这个下标所指示的柱子高度计算面积。而这个方法为什么只需要一个栈呢?因为当第二种情况时,for循环的循环下标回退,也就让下一次for循环比较当前柱子高度与新的栈顶下标所指示的柱子高度,注意此时的栈顶已经改变。

C++代码实现:
方法一

#include <iostream>#include <queue>using namespace std;int n;int height[10000];long long maxArea(){    long long result = 0,area = 0;    for(int i=0; i<n; i++){        for(int k=i+1; k<n; k++){            if(height[k-1] > height[k]){                i = k - 1;  //右边界                break;            }            else                i = k;        }        int lowest = height[i];        for(int j=i; j>=0; j--){            lowest = lowest<height[j]?lowest:height[j];            area = lowest*(i-j+1);            if(area>result)                result = area;        }    }    return result;}int main(){    cin>>n;    for(int i=0; i<n; i++)        cin>>height[i];    cout<<maxArea();    return 0;}

方法二

#include <iostream>#include <queue>using namespace std;int n=1;int height[10000];long long maxArea(){    long long result = 0,area = 0;    int left[n], right[n];    int i=0,j=0;    //查找每根柱子的左边界    left[0] = 0;    for( i=1; i<n; i++){        j = i;        while(j>=1 && height[j-1]>=height[i])            j--;        left[i] = j;    }    //查找每根柱子的右边界    right[n-1] = n-1;    for(int i=n-2; i>=0; i--){        j = i;        while(j<n-1 && height[j+1]>=height[i])            j++;        right[i] = j;    }    for(int i=0; i<n; i++){        area = (right[i]-left[i]+1)*height[i];        if(area>result)            result = area;    }    return result;}int main(){    cin>>n;    for(int i=0; i<n; i++)        cin>>height[i];    cout<<maxArea();    return 0;}

方法三:

#include <iostream>#include <stack>using namespace std;int n=1;int height[10000];long long maxArea(){    long long result = 0,area = 0;    int start = 0;    stack<int> rectangle;    for(int i=0; i<n; i++){        if(rectangle.empty() || height[rectangle.top()] < height[i])            rectangle.push(i);        else{            start = rectangle.top();            rectangle.pop();            if(rectangle.empty())                area = height[start]*i;            else                area = height[start]*(i-rectangle.top()-1);            if(area>result)                result = area;            i--;        }    }    while(!rectangle.empty()){        start = rectangle.top();        rectangle.pop();        if(rectangle.empty())            area = height[start]*n;        else            area = height[start]*(n-rectangle.top()-1);        if(area>result)                result = area;    }    return result;}int main(){    cin>>n;    for(int i=0; i<n; i++)        cin>>height[i];    cout<<maxArea();    return 0;}

[编程题] 最长公共连续子串

时间限制:1秒
空间限制:32768K
给出两个字符串(可能包含空格),找出其中最长的公共连续子串,输出其长度。
输入描述:
输入为两行字符串(可能包含空格),长度均小于等于50.
输出描述:
输出为一个整数,表示最长公共连续子串的长度。
输入例子1:
abcde
abgde
输出例子1:
2

解析:

动态规划。dp[i][j]表示子串Xi和Yj的最长连续公共子串的长度。
如果x[i]==y[j],则dp[i+1][j+1] = dp[i][j] + 1
其中最大的dp[i][j],即为X和Y的最长连续公共子串。

C++代码实现

#include <iostream>using namespace std;string x,y;int dp[51][51] = {0};int maxLength(){    int lenX = x.size();    int lenY = y.size();    int result = 0;    for(int i=0; i<lenX; i++)        dp[i][0] = 0;    for(int j=0; j<lenY; j++)        dp[0][j] = 0;    for(int i=0; i<lenX; i++){        for(int j=0; j<lenY; j++){            if(x[i]==y[j])                dp[i+1][j+1] = dp[i][j]+1;            if(dp[i+1][j+1]>result)                result = dp[i+1][j+1];        }    }    return result;}int main(){    getline(cin,x);    getline(cin,y);    cout<<maxLength();    return 0;}