题解 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;
}