poj3629 Card Stacking
noi.openjudge.cn 2049 Card Stacking
http://noi.openjudge.cn/ch0304/2406/
题目大意:
贝斯和奶牛们玩牌共n个队员玩k张牌,分牌时候,每轮先分给奶牛,再分给贝斯,每次分给一个队员牌后,将牌前面的q张牌按顺序放在后面,给出最后贝斯的排,按照从小到大排好序。
数据范围: k:10^5 n 100 p 10
题目分析:队列模拟
先用普通队列,开了数组10^6, k*p,结果不过,看了别人的提示,开到6*10^6才过,现在也没算明白为什么要这么大。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<cstring>
using namespace std;
int n,k,p;
int q[6000010]={0},head,tail,cnt=0,a[100011];
int main(){
scanf("%d%d%d",&n,&k,&p);
memset(q,0,sizeof(q));
for(int i=1;i<=k;i++)
q[i]=i;
head=1;tail=k+1;cnt=0;
for(int i=1;i<=k;i++){
if(i%n==0)//到贝斯的牌
a[++cnt]=q[head];
head++; //发牌,队首出队;
for(int j=1;j<=p;j++) //移动p张牌到后面去。
q[tail++]=q[head++];
}
sort(a+1,a+1+cnt);
for(int i=1;i<=cnt;i++)
printf("%d\n",a[i]);
}
采用循环队列:
最多只有n张牌,采用循环队列节省空间,判断队列为空的条件是head!=tail
队头指针和队尾指针移动时候,要根据取模来移动:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<cstring>
using namespace std;
const int N=100010 ;
int n,k,p;
int q[N]={0},head,tail,cnt=0,a[N];
int next(int &x){//地址引用,直接改变参数的值。
x++;
if(x>=k)x-=k;
return x;
}
int main(){
scanf("%d%d%d",&n,&k,&p);
memset(q,0,sizeof(q));
for(int i=0;i<k;i++)
q[i]=i+1;
head=0;tail=k-1;cnt=0;
for(int i=1;i<=k;i++){
if(i%n==0)
a[++cnt]=q[head];
next(head); //循环队列队头指针后移
for(int j=1;j<=p;j++){
q[next(tail)]=q[head];
next(head); //循环队列队尾指针后移
}
}
sort(a+1,a+1+cnt);
for(int i=1;i<=cnt;i++)
printf("%d\n",a[i]);
}
本题数据用stl直接超时。