15.卡牌游戏

解决小张如何通过最少操作调整牌堆,使之按1到n顺序排列的问题,涉及数组操作和动态策略。
摘要由CSDN通过智能技术生成
Description

小张在玩一种卡牌游戏,牌组由 2n 张牌组成,其中 n 张上写有数字 1…n 各一张,其余

n 张上全部是数字 0。

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

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

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

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

Input

第一行一个数

n(1 \leq n \leq 200000 )

第二行 n 个数,表示小张手中的牌。

第三行 n 个数,表示牌堆,数组从左向右的顺序表示牌堆自顶向下的顺序。

Output

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

测试输入期待的输出时间限制内存限制额外进程
测试用例 1以文本方式显示
  1. 3↵
  2. 0 2 0↵
  3. 3 0 1↵
以文本方式显示
  1. 2↵
1秒64M0
测试用例 2以文本方式显示
  1. 3↵
  2. 0 2 0↵
  3. 1 0 3↵
以文本方式显示
  1. 4↵
1秒64M0

思路

本题的输入其实手牌是不必要的。建立两个数组,一个存放牌堆,一个存放数字牌所在牌堆中的位置。
首先判断牌堆底部是否存在1~t的连续牌。注意判断连续的时候边界条件取好,注意最末是0的情况(11.13用例牌堆末尾应该是0,当时因为边界没取好,直接就没进去循环,flag=1死活过不了)。接下来就是判断当放置牌i时,它是否在手牌中。比如45012,3在手牌中可以;需要放4时,已插入4-1-2=1张牌,使4的位置从1变成0,在手牌中;需要放5时,已插入5-1-2=2张牌,使5的位置从2变成0,在手牌中。保证此后每一张牌都能满足即可,此时答案为缺着的牌数5-2=3。而34512,需要放置3时,它的位置是1,无法完成。此时需要多进行n+1轮(如果n轮最多恢复,多一轮操作可以使其满足。先放4张0得到1,成为20000,然后就可以依次放置1~5)
如果不存在连续牌。i在牌堆中的位置-最终位置+1,才能保证该放置i时它在手牌里。比如牌堆 25300,要先放置3-3+1个0,才能使得放置2后3恰好在牌顶(或手牌)。取所有牌中该式最大值再+n即可

代码
#include<stdio.h>
#define N 200010
int list[N]={0},pile[N]={0};

main()
{
	int n,temp,i,flag=1,max=0,m=0;
	long long ans=0;
	scanf("%d",&n);
	/*输入,list记录牌1-n位置,pile表示牌堆*/
	for(i=0;i<n;i++){
		scanf("%d",&temp);
		list[temp]=0;
	}
	for(i=1;i<=n;i++){
		scanf("%d",&temp);
		pile[i]=temp;
		list[temp]=i;
	}

	/*检查牌堆底部是否存在1开始的连续数字*/
	if(pile[n]==0)	flag=0;
	for(i=n,temp=pile[n];temp>0;i--,temp--){
		if(pile[i]!=temp){
			flag=0;
			break;
		}
	}
	/*如果存在*/
	if(flag==1){
		for(i=pile[n]+1;i<=n;i++){
			//判断下一步应放置的手牌是否可以及时获取
			if(list[i]>i-(pile[n]+1)){
				m=-1;
				break;
			}
		}
		if(m==-1)
		//n-card[n]+1将1及以上的数字拿到手(此时牌堆顶为2),+n为放置1~n(边放遍拿
			ans=n-pile[n]+1+n;
		else	ans=n-pile[n];	//直接放置缺着的牌即可
	}
	/*无连续*/
	else
	{
		for(i=1;i<=n;i++){
			if(list[i]-(i-1)>max)
				max=list[i]-i+1;

//			temp = (pile[i] - i + 1) > 0 ? (pile[i] - i + 1) : 0;
//			if (temp > max)
//			{
//				max = temp;
//			}
		}
		ans=n+max;
	}
	
	printf("%lld\n",ans);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北辰2023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值