牛客网OJ题解--20210224

入学考试

https://ac.nowcoder.com/acm/problem/14370

本系列记录翀翀😐痛苦的刷题日志,所有题目均来自于牛客网OJ题目,坚持刷题谈起来容易做起来难,希望我可以坚持下去,这里仍然分享一段励志文案:每个人都有梦想,然而有些人把梦想变成了现实,有些人的梦想依旧是梦想,只因为他们为梦想付出的努力程度不一样,他们坚持的时间不一样,最终才有这样的结果。

NC14370-入学考试

题目链接

https://ac.nowcoder.com/acm/problem/14370

题目描述

马云是个聪明的孩子,他想成为世界上最伟大的医师。所以他想拜附近最有威望的张丹成为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”如果你是马云,你能完成这个任务吗?(注:马云啥的是编的 。。)第一行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。

第一行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。

测试样例

输入

70 3
71 100
69 1
1 2

输出

3

解题思路

贪心和k-优化算法不好实现,典型的0/1背包动态规划板子题,如果使用二维数组请参考本篇文章《动态规划》,但是这里又学习到了二维到一维数组优化的算法,请参考本篇文章《浅谈用一维数组dp解决0/1背包问题》。

解题代码

#include <bits/stdc++.h>
using namespace std;

int f[1005], t[1005], v[105];

int T, n, i, j;
int main()
{
    cin >> T >> n;
    for (i = 1; i <= n; i++)
        cin >> t[i] >> v[i];
    //f[i]物品1~i范围选取
    for (i = 1; i <= n; i++)
        //注意,逆序是逆序的即背包容量从大到小,fot已经特判能否装入
        for (j = T; j >= t[i]; j--)
            //右边的都是第i-1次循环的结果
            f[j] = max(f[j], f[j - t[i]] + v[i]);
    cout << f[T] << endl;
    system("pause");
    return 0;
}

NC14381-蝴蝶

题目链接

https://ac.nowcoder.com/acm/contest/profile/126727419/practice-coding

题目描述

给定一个 n*m 的矩阵,矩阵元素由X和O构成,请求出其中最大的蝴蝶形状。
蝴蝶形状的定义如下:
存在一个中心点(必须为X),并且其往左上(必须为X)、左下(必须为X)、右上(必须为O)、右下(必须为O)四个方向扩展相同的长度,且左上顶点与左下顶点之间全由X填充,右上顶点与右下顶点之间全由O填充。我们不在意在蝴蝶形状内部是X还是O。例如:

是一个蝴蝶形状(其中A表示X或O)。并且X是大小为1的蝴蝶。而、

不是(不存在中心点)。

第一行两个整数n, m表示矩阵的大小 (1 <= n, m <= 500),接下来 n 行,每行一个长度为 m 的字符串表示矩阵,矩阵元素保证由X和O构成。一行一个整数表示最大的蝴蝶形状的对角线的长度。

测试样例

输入

5 5
XOOOO
XXOOO
XOXOO
XXOOO
XOOOO

输出

5

解题思路

该死,这题一开始读错题意了。一定要注意他要求的是顶点之间的字符必须相同,即如样例1的蝴蝶左上角顶点和左下角顶点之间也要都为X,右上角顶点和右下角顶点也要为O才可以。

即红色线部分要满足左半部分全是X,右半部分全是O,同时蓝线的左半部分要全部是X,右半部分全是O。我们只需要先逐一枚举中心点,如果满足中心点为X,那么沿四个方向延伸检验是否红色线满足题意,如果满足再检验蓝色线部分是否满足。最会取得最大值的情况就可以了。

解题代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

char Map[505][505];
int n, m;

bool flag(int x, int y)
{
    //检验是否越界的函数
    if (x >= 0 && x < n && y >= 0 && y < m)
        return 1;
    else
        return 0;
}

int main()
{

    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
            cin >> Map[i][j];
    }
    int ans = 0;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            //因为是四个方向检查,所以需要四个方向临时点
            int x1, y1, x2, y2, x3, y3, x4, y4;
            //寻找中心点
            if (Map[i][j] != 'X')
                continue;
            ans = max(ans, 1);
            for (int len = 1; len <= min(n, m) / 2; len++)
            {
                int valid = 1;
                //算出四个方向的从中心点移动后的顶点位置
                x1 = i - len;
                y1 = j - len;
                x2 = i + len;
                y2 = j - len;
                x3 = i - len;
                y3 = j + len;
                x4 = i + len;
                y4 = j + len;
                //检验是否越界
                if (flag(x1, y1) && flag(x2, y2) && flag(x3, y3) && flag(x4, y4))
                {
                    //如果都不越界,那么检验顶点值是否满足题意
                    if (Map[x1][y1] == 'X' && Map[x2][y2] == 'X' && Map[x3][y3] == 'O' && Map[x4][y4] == 'O')
                    {
                        //满足以后分别检验顶点中间的值是否满足题意
                        for (int l = x1; l <= x2; l++)
                        {
                            if (Map[l][y1] != 'X')
                            {
                                valid = 0;
                                break;
                            }
                        }
                        for (int l = x3; l <= x4; l++)
                        {
                            if (Map[l][y3] != 'O')
                            {
                                valid = 0;
                                break;
                            }
                        }
                        //满足题意就为斜边长的2倍再+1(因为有一个中心点)
                        if (valid)
                            ans = max(ans, len * 2 + 1);
                    }
                    else
                        break;
                }
                else
                    break;
            }
        }
    }
    cout << ans << endl;
    system("pause");
    return 0;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务