Description
小张在玩一种卡牌游戏,牌组由 2n 张牌组成,其中 n 张上写有数字 1…n 各一张,其余
n 张上全部是数字 0。
现在牌组经过随机打乱后,小张拿走其中 n 张牌作为手牌,其余 n 张牌作为牌堆。
小张想经过若干次如下操作使得牌堆自顶向下的牌依次为 1…n
每一次操作,小张选择任意一张手牌放到牌堆底,并将牌堆顶的牌放入手牌。
他想知道最少进行几次操作,使得牌堆自顶向下的牌依次为 1…n 。
Input
第一行一个数
第二行 n 个数,表示小张手中的牌。
第三行 n 个数,表示牌堆,数组从左向右的顺序表示牌堆自顶向下的顺序。
Output
一个整数,表示最少执行的操作数。
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
测试用例 2 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M | 0 |
思路
本题的输入其实手牌是不必要的。建立两个数组,一个存放牌堆,一个存放数字牌所在牌堆中的位置。
首先判断牌堆底部是否存在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);
}