C++笔试强训day4

目录

1.游游的you

2.腐烂的苹果

3.孩子们的游戏


1.游游的you

链接:

分析题意之后,发现就是一道简单的贪心,当然也可以把他看作纯数学题。

因为you和oo里面都有o,但是you可以得两分,所以贪心策略尽可能的去凑更多的you,剩下的o则是n - 1分。

详细代码:

#include <iostream>
using namespace std;

int x,y,z;

int main() {
    int n;
    cin >> n;

    while(n--)
    {
        cin >> x >> y >> z;

        int mi = min(x,min(y,z));

        y -= mi;
        if(y > 0)
            cout << mi * 2 + y - 1 << endl;
        else
            cout << mi * 2 << endl;
    }   
}

注意:

要判断剩下的y是否大于0,不然会导致部分样例出错。

2.腐烂的苹果

链接

我一开始分析这道题目的时候,想到的竟然是DFS遍历,压根做不出来,因为做不到多源搜索。

正解应该是BFS的多源搜索。

首先先遍历grid,将所有的腐烂苹果存入队列,进行多源搜索。

最后需要返回的时候应该判断有没有苹果1没被感染到。

详细代码:

class Solution {
public:
    const static int N = 1010;
    int dx[4] = { 0, 0, 1, -1 };
    int dy[4] = { 1, -1, 0, 0 };
    bool vis[N][N] = { false };
    int m, n;
    int time = 0;

    queue<pair<int, int>> q;

    void BFS(vector<vector<int> >& grid) {

        while (q.size()) {
            time++;
            int size = q.size();
            while (size--) {
                int x = q.front().first;
                int y = q.front().second;
                q.pop();

                for (int i = 0; i < 4; ++i) {
                    int a = x + dx[i];
                    int b = y + dy[i];

                    if (a >= 0 && a < m && b >= 0 && b < n
                        && grid[a][b] == 1 && !vis[a][b]) {
                        vis[a][b] = true;
                        q.push({ a, b });
                    }
                }
            }
        }
    }

    int rotApple(vector<vector<int> >& grid) {
        m = grid.size();
        n = grid[0].size();

        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == 2) {
                    q.push({ i, j });
                }
            }
        }

        // BFS遍历
        BFS(grid);
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == 1 && !vis[i][j])
                    return -1;
            }
        }

        return time - 1;//最后的苹果还会进行一次无效遍历  减掉那次
    }
};

怎么说呢,算是一道比较难的题目吧,个人觉得。

3.孩子们的游戏

链接

就是约瑟夫的环形链表。

方法一:模拟

可以用环形链表或者数组来模拟实现:

(这里我写的是环形链表)

class Solution {
public:
    typedef struct ListNode ListNode;

    ListNode* ListBuyNode(int x) {
        ListNode* node = (ListNode*)malloc(sizeof(ListNode));
        if (node == NULL) {
            perror("malloc fail!");
            exit(1);
        }
        node->val = x;
        node->next = NULL;
        return node;
    }

    //创建带环链表
    ListNode* CreateList(int n) {
        ListNode* phead = ListBuyNode(1);
        ListNode* ptail = phead;
        for (int i = 2; i <= n; i++) {
            ListNode* node = ListBuyNode(i);
            ptail->next = node;
            ptail = ptail->next;
        }
        ptail->next = phead;
        return ptail;
    }

    //n = 5;m = 2;
    int LastRemaining_Solution(int n, int m) {
        ListNode* prev = CreateList(n);
        ListNode* cur = prev->next;
        int count = 1;
        while (cur->next != cur) {
            if (count == m) {
                //杀掉
                prev->next = cur->next;
                free(cur);
                cur = prev->next;
                count = 1;
            }
            else {
                prev = cur;
                cur = cur->next;
                count++;
            }
        }
        return cur->val - 1;
    }
};

减一是因为我写的是从1开始的,而题目是从0开始。

方法二:递推/ 动态规划

就是只需要寻找 dp[n] 和 dp[n - 1] 的映射关系就好了。

图中所画的内环是i - 1,外环是i。分析很容易得到dp[i]与dp[i - 1]的关系为dp[i] = dp[i - 1] + m。

最后为了防止+m后超出n,因此模上一个n(目前的数量)。

因此:

class Solution 
{
  public:
    int dp[5010];
    
    int LastRemaining_Solution(int n, int m) 
    {
        dp[1] = 0;
        for (int i = 2; i <= n; i++) 
            dp[i] = (dp[i - 1] + m) % i;
        return dp[n];
    }
};

因为只有一维,而且状态转移方程只涉及一个数,也可以不创建dp表,用一个变量来表示。

class Solution
{
public:
    int LastRemaining_Solution(int n, int m)
    {
        int f = 0;
        for (int i = 2; i <= n; i++) f = (f + m) % i;
        return f;
    }
};
  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值