题解 P2348 【三国杀I(洗牌&发牌)】
这道题其实不难,不要一看到题目这么长就被吓到,普及/提高-的难度,其实不难,就是整太多花里胡哨的了。
这里帮大家整理一下有用的部分:
topic1: n个参加游戏玩家,每人需要4张牌牌库共k张牌.
topic2:洗牌方式:k/2+1,1,k/2+2,2,k/2+3,3, ... ,k,k/2。 发牌方式:从第1张牌开始,第i张牌给第(i-1)%n+1个人 共洗m次牌,你是第p个人,问你得到了哪几张牌
topic3:若牌数不够输出Error:cards not enough。
看了一下其它人的题解,都是用字符串直接比较,而字符串的比较是非常慢的,所以可以用int类型的数组存储下标,我两种方法都试过了,请看。
字符串串直接比较 数组存储下标比较
两者相差了近5倍的时间
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=100005;
char s[maxn][10];//char两维数组存储,等同于string s[maxn],但char类型不知道为什么更快
int a[maxn],b[maxn];//a数组用来存储下标,字符串的赋值速度很慢
int main()
{
int n,m,x,y;
cin>>n>>m>>x>>y;
gets(s[1]);
if(n*4>m) //若牌数不够输出Error:cards not enough
{
puts("Error:cards not enough");
return 0;
}
for(int i=1; i<=m; ++i)gets(s[i]);
for(int i=1; i<=m; ++i)a[i]=i;//数组下标初始化
for(int i=1; i<=x; ++i)
{
for(int j=1; j<=m; j+=2)
b[j]=a[m/2+(j+1)/2];
for(int j=2; j<=m; j+=2)
b[j]=a[j/2];
memcpy(a,b,sizeof(a));//把b数组的值赋给a数组
}
x=0;//x到现在为止已经没有用了,可以用来存储目前已经输出了多少个
for(int i=1; i<=m&&x<4; ++i)
{
if((i-1)%n+1==y)
{
cout<<s[a[i]];
x++;
putchar('\n');
}
}
//for(int i=1;i<=m;i++)
//cout<<'\n'<<s[i]<<' '<<a[i];
return 0;
}