牛客网OJ题解--20210228

B-苦逼的单身狗

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

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

NC14547-苦逼的单身狗

题目链接

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

题目描述

双11又到了,小Z依然只是一只单身狗,对此他是如此的苦恼又无可奈何。 为了在这一天脱单小Z决定向女神表白,但性格腼腆的小Z决定隐晦一点,截取一段包含'L'、'O'、'V'、'E'的英文。(顺序不限)。小Z想起之前小D送给他一本英文书,决定在这里面截取一段话,小Z发现有好多种方案来截取这段话。 你能知道小Z能有多少种方案截取这段话么? 为了简化问题,英文文本讲不会出现空格、换行、标点符号及只有大写的情况。

本题有T组数据。对于每组数据只有一行文本。1≤T≤20,1≤文本长度≤100000。

测试样例

输入

3
ILOVEACM
LOVELOVE
ALBECVOD

输出

8
15
4

解题思路

我们以LOVELOVE为例分析一下,每次我们都找到含有LOVE(顺序随意)的子串,然后记录这四个字符最早出现的位置,然后左边的字符数+1就包含这个子串的所有情况。比如现在从i=1开始向右查找。

  1. i=0(L),i=1(O),i=2(V),i=3(E),那么最早出现的位置是i=0,左边无字符,所以字符数是0,那么包含这个子串的情况就是有一种即子串自身LOVE
  2. i=1(O),i=2(V),i=3(E),i=4(L),那么最早出现的位置是i=1,左边有一个字符L,所以字符数是1,那么包含这个子串的情况就有2种即LOVEL和OVEL
  3. i=2(V),i=3(E),i=4(L),i=5(O),那么最早出现的位置是i=2,左边有两个字符L,O,所以字符数是2,那么包含这个子串的情况3种即LOVELO,OVELO和VELO

依次类推,所以我们就找到了规律,即每次获取刚好出现LOVE的子串,然后比较获得四个字符最先出现的位置,查看左边的字符数即可。

解题代码

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

int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        string s;
        cin >> s;
        //记录四个字符出现的坐标
        int l = -1, o = -1, v = -1, e = -1;
        long long ans = 0;
        for (int i = 0; i < s.length(); i++)
        {
            if (s[i] == 'L')
                l = i;
            else if (s[i] == 'O')
                o = i;
            else if (s[i] == 'V')
                v = i;
            else if (s[i] == 'E')
                e = i;
            //取一个含有字符串的love的子串并且比较四个坐标取最小值
            int cnt = min(min(l, o), min(v, e));
            if (cnt != -1)
            {
                //包含本次子串的情况数量为左边的字符数+1
                ans += cnt + 1;
            }
        }
        cout << ans << endl;
    }
    system("pause");
    return 0;
}

NC14545-B-经商

题目链接

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

题目描述

小d是一个搞房地产的土豪。每个人经商都有每个人经商的手段,当然人际关系是需要放在首位的。 小d每一个月都需要列出来一个人际关系表,表示他们搞房地产的人的一个人际关系网,但是他的精力有限,对应他只能和能够接触到的人交际。比如1认识2,2认识3,那么1就可以接触3进行交际,当然1和2也可以交际。 小d还很精明,他知道他和谁交际的深获得的利益大,接下来他根据自己的想法又列出来一个利益表,表示他和这些人交际需要耗用多少精力,能够获得的利益值为多少。小d想知道,他在精力范围内,能够获得的利益值到底是多少。 设定小d自己的编号为1.并且对应一个人的交际次数限定为1。

本题包含多组输入,第一行输入一个数t,表示测试数据的组数
每组数据的第一行输入三个数,N,M,C,表示这个人际关系网一共有多少个人,关系网的关系数,以及小d的精力值
接下来N-1行,每行两个数ai,bi。这里第i行表示和编号为i+1的人认识需要花费ai的精力,能够获得的利益值为bi。
再接下来M行,每行两个数x,y,表示编号为x的人能够和编号为y的人接触
t<=50
2<=N<=10000
1<=M<=10*N
1<=ai,bi<=10
1<=C<=500
1<=x,y<=N

测试样例

输入

1
5 3 7
5 10
3 2
4 3
1 100
1 2
2 3
1 4

输出

10

解题思路

这是一道并查集+0/1背包dp题,可以参考学习笔记《浅谈用一维数组dp解决0/1背包问题》和《浅谈并查集解决分组问题》。这里就是纯板子题,但是一定要注意读懂题干,是要求只有两个人有直接关系或者间接关系才可以认识,例如样例1中的1和5是不能认识的,虽然给出了1认识5的精力消耗和收益,但是由于1和5没有直接关系并且1也不能通过该其他人认识5。所以这道题就是先试用并查集建立分组关系网,然后使用0/1背包dp解决。

解题代码

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

#define ll long long
#define close_stdin ios::sync_with_stdio(false)
int n, m, c;
const int maxn = 10005;
int a[maxn], b[maxn];
int fa[maxn];
int dp[505];

int find(int x)
{
    //寻找最深层祖先,同时压缩更新x的祖先为最深层祖先
    return (fa[x] == x ? x : fa[x] = find(fa[x]));
}

void merge(int x, int y)
{
    //x的最深层祖先的祖先更新为y,这样x和y就有关系了,同时y会成为更深层的根本祖先
    if (find(x) != find(y))
        fa[find(x)] = find(y);
}

void my_input()
{
    cin >> n >> m >> c;
    for (int i = 2; i <= n; i++)
    {
        cin >> a[i] >> b[i];
    }
}

void solve()
{
    memset(dp, 0, sizeof(dp));
    for (int i = 1; i <= n; i++)
    {
        //初始时默认是独立节点,无祖先,所以各节点无关系
        fa[i] = i;
    }
    while (m--)
    {
        int x, y;
        cin >> x >> y;
        //x和y建立关系同时默认y是更深层的祖先
        //所以此时fa[x]=y即x的最根本祖先是y
        //同时fa[find(X)]=y即x的祖先的最根本祖先也会是y
        merge(x, y);
    }
    //关系网建立完成后进行0/1dp
    for (int i = 2; i <= n; i++)
    {
        //讨论每一个对于1~i每一个节点是否放入
        //首先需要满足有关系才可以认识
        //一定要注意例如样例1中1和5就不能认识,因为他们没有共同认识的人且两者也不认识
        if (find(i) == find(1))
        {
            //能够认识,讨论是否认识
            for (int j = c; j >= a[i]; j--)
            {
                //板子
                dp[j] = max(dp[j], dp[j - a[i]] + b[i]);
            }
        }
    }
    cout << dp[c] << endl;
}

int main()
{
    close_stdin;
    int t;
    cin >> t;
    while (t--)
    {
        my_input();
        solve();
    }
    system("pause");
    return 0;
}
全部评论

相关推荐

Lorn的意义:我的前辈都劝我年后再投,说那时候会好一点
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务