美团点评秋招编程题

[编程题] 大富翁游戏

时间限制: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;
}

猜你喜欢

转载自blog.csdn.net/peaktravel/article/details/77817303
今日推荐