卡牌游戏(C++语言)

文章讨论了如何在卡牌游戏中,通过最少的操作次数将牌堆调整为1到n的顺序,给定初始手牌和牌堆状态,利用递归算法求解最优操作数。
摘要由CSDN通过智能技术生成

描述问题
小张在玩一种卡牌游戏,牌组由 2n 张牌组成,其中 n 张上写有数字 1...n 各一张,其余 n 张上全部是数字 0 。

现在牌组经过随机打乱后,小张拿走其中 n 张牌作为手牌,其余 n 张牌作为牌堆。  

小张想经过若干次如下操作使得牌堆自顶向下的牌依次为 1...n 。

每一次操作,小张选择任意一张手牌放到牌堆底,并将牌堆顶的牌放入手牌。

他想知道最少进行几次操作,使得牌堆自顶向下的牌依次为 1...n 。  

Input
第一行一个数 n(1 n 200000 ) 。  
第二行 n 个数,表示小张手中的牌。  
第三行 n 个数,表示牌堆,数组从左向右的顺序表示牌堆自顶向下的顺序。  

Output
一个整数,表示最少执行的操作数。


样例

输入(1)

3
0 2 0
3 0 1

输出(1)

2

输入(2)

3
0 2 0
1 0 3

输出(2)

4

代码

#include <stdio.h>
#include <stdbool.h>

int max(int a, int b) { return a > b ? a : b; }

void input(void);
bool canReachOne(void);
void evaluate(bool);

#define MAX_SIZE 200010

int operation_count[MAX_SIZE], cards[MAX_SIZE];

int temp, num_cards, i, result = 0, additional_steps = 0;

int main(void)
{
    input();
    evaluate(canReachOne());
    printf("%d\n", result);

    return 0;
}

void input(void)
{
    scanf("%d", &num_cards);
    for (i = 1; i <= num_cards; i++)
    {
        scanf("%d", &temp);
        operation_count[temp] = 0;
    }
    for (i = 1; i <= num_cards; i++)
    {
        scanf("%d", &temp);
        cards[i] = temp;
        operation_count[temp] = i;
    }
}

bool canReachOne(void)
{
    int temp;
    temp = cards[num_cards];
    for (i = num_cards - 1; temp != 1; i--)
    {
        if (cards[i] != --temp)
        {
            return false;
        }
    }
    return true;
}

void evaluate(bool success)
{
    bool one_loop = true;
    if (success)
    {
        for (i = cards[num_cards] + 1; i <= num_cards; i++)
        {
            if (operation_count[i] > i - (cards[num_cards] + 1))
            {
                one_loop = false;
                break;
            }
        }
        if (one_loop)
        {
            result += num_cards - cards[num_cards];
        }
        else
        {
            result += num_cards + 1 + num_cards - cards[num_cards];
        }
    }
    else
    {
        for (i = 1; i <= num_cards; i++)
        {
            temp = max(operation_count[i] - (i - 1), 0);
            if (temp > additional_steps)
            {
                additional_steps = temp;
            }
        }
        result += additional_steps;
        result += num_cards;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值