美文网首页
牛客——01反转

牛客——01反转

作者: Myth52125 | 来源:发表于2017-09-24 08:51 被阅读0次

1. 01反转

题目

牛牛正在挑战一款名为01翻转的游戏。游戏初始有A个0,B个1,牛牛的目标就是把所有的值都变为1,每次操作牛牛可以任意选择恰好K个数字,并将这K个数字的值进行翻转(0变为1,1变为0)。牛牛如果使用最少的操作次数完成这个游戏就可以获得奖品,牛牛想知道最少的操作次数是多少?

例如:A = 4 B = 0 K = 30000 -> 1110 -> 1001 -> 0100 -> 1111

需要的最少操作次数为4

思路

使用广度优先搜索,倒着向后遍历,从最终状态到起始状态。
因为每条路径上边的全都都可以看作为1,所以如果之前遍历了,那么之前的一定比后面的路径(步数)少,所以之前遍历了,后面再遇到就跳过。

#include <iostream>
#include <deque>
#include <vector>

using namespace std;
struct Node
{
    Node(int a, int step, int f)
        : a(a), step(step), f(f)
    {
    }
    int a;    //当前1的个数
    int step; //距离权为1的步数
    int f;    //上次1的个数
};

//a:1的个数,b:0的个数,k每次反转的次数。
int turn0to1Counts(int a, int b, int k)
{
    int total = a + b;

    vector<Node> memo(total + 1, Node(-1, -1, -1));
    deque<Node> de;

    //将最后一步放入队列
    Node end{total, 0, -1};
    de.push_back(end);
    //每次可能盛夏的
    int remain1;
    memo[total] = Node(total, 0, -1);
    cout << "de add: " << de.back().a << " " 
        << de.back().step << " " << de.size() << endl;
    
    while (!de.empty())
    {
        Node n = de.front();
        cout << "now : " << n.a << " " << n.step << " " << n.f << endl;
        
        //如果目前正在处理的节点,等于初始状态,表明,已经遍历到了最终结果。
        if (n.a == a)
        {
            return n.step;
        }
        de.pop_front();

        cout << "\n_______" << n.a << " :from_______" << endl;
        
        //判断可能的反转情况:
        //反转1变为0的个数:从0到目前的1正面的数目,依次遍历,但不能超过k
        //因为不能一次反转k+1个1,所以,大于的要略去
        for (int i = 0; i <= n.a && i<=k; i++)
        {
            //原有1的个数+每次能反转的K个数-反转的1个数 应该小于总数
            //这里相当于,两个部分叠加,减去重叠部分的长度,不能超过总长
            if (n.a+k-i<=total)
            {
                remain1 = n.a -i + (k-i);
                //记录已经出现,那么就不要在遍历了。
                if (memo[remain1].a == -1)
                {
                    de.push_back(Node(remain1, n.step + 1, n.a));
                    memo[remain1] = Node(remain1, n.step + 1, n.a);
                    cout << "de add: " << de.back().a << " " 
                        << de.back().step << " " << de.size() << endl;
                }
            }
        }
        cout << "_______" << n.a << "_______\n" << endl;
    }
    //上面没有找到可能的反转
    return -1;
}

int main()
{
    int a, b, k;
    cin >> a >> b >> k;
    cout << "count :" << turn0to1Counts(a, b, k) << endl;
}

上面主要在于判断,下一次反转1可能的个数。
理清这个就好了。
(可怜的我,理了一晚上,才搞出来)

相关文章

  • 牛客——01反转

    1. 01反转 题目 牛牛正在挑战一款名为01翻转的游戏。游戏初始有A个0,B个1,牛牛的目标就是把所有的值都变...

  • 反转链表【牛客网】

    题目描述输入一个链表,反转链表后,输出新链表的表头。

  • 反转链表

    题目来源:牛客网--反转链表 题目描述 输入一个链表,反转链表后,输出新链表的表头。 解题思路 要考虑两种情况:1...

  • 剑指offer(十五)反转链表

    点击进入 牛客网题库:反转链表 题目描述输入一个链表,反转链表后,输出新链表的表头。 上来,想了10分钟,然后就撸...

  • 反转链表

    题目描述 输入一个链表,反转链表后,输出新链表的表头。 分析 理清逻辑 代码 参考链接 牛客网

  • 01背包问题-HJ16 购物单

     牛客测试地址,01背包[https://www.nowcoder.com/practice/2820ea076d...

  • 牛客网高频算法题系列-BM2-链表内指定区间反转

    牛客网高频算法题系列-BM2-链表内指定区间反转 题目描述 将一个节点数为 size 链表 m 位置到 n 位置之...

  • 牛客-剑指0ffer-反转链表

    题目描述输入一个链表,反转链表后,输出新链表的表头。

  • 回馈牛客,秋招历程和感悟

    作者:走路不怕滑来源:牛客网、招聘消息汇总 回馈牛客,秋招历程和感悟。大三开始刷牛客到现在,感谢牛客网的帮助,写了...

  • 牛客网高频算法题系列-BM1 反转链表

    牛客网高频算法题系列-BM1 反转链表 题目描述 给定一个单链表的头结点pHead(该头节点是有值的),长度为n,...

网友评论

      本文标题:牛客——01反转

      本文链接:https://www.haomeiwen.com/subject/qutkextx.html