题意:

  • 洗一个洗牌程序,牌的初试状况是S1~S13,H1~H13,C1~C13,D1~D13,J1,J2;
  • 按照如下规则洗牌:输入一组数,如果位置i的数为j,那么就将牌中第i张牌与第j张牌置换,再根据给定的k决定进行几次洗牌;
  • 比如:有五张牌:S3, H5, C1, D13 和 J2 按照{4, 2, 5, 3, 1}洗牌,就会变成J2, H5, D13, S3, C1,比如第一位为4,那么就是将牌中第一张牌S3与第四张牌D13换位,然后依次进行,将这种行为进行两次会得到:C1, H5, S3, J2, D13.(具体进行几次洗牌,根据给定的k来决定)

思路:

  1. 因为题中牌有花色,如果直接存储字符和数字会很麻烦,所以我们利用一种转换关系来处理,发现每种花色都是13张(除了Joker,但不影响解题),那么我们直接存储牌号k(也就是这张牌在所有牌中的顺序,例如S2是第二张,H1是第十四张),再将花色存储在一个数组mp[]={'S','H','C','D'}中那么用mp[(k-1)/13]就是这张牌对应的花色,那么这张牌对应花色的数字是mp[(k-1)%13+1];(这里太理解的话可以举个例子,例如H1的牌序是14,那么(14)-1/13=1即是红桃H,数字是(14-1)%13+1=1,即得出这张牌是H1);
  2. 做完第一步我们就知道了牌序可以与每张牌相对应;
  3. 下一步我们要用一个数组next[]来接收洗牌的序列,然后在定义一个start[],和end[]数组,分别表示洗牌前的牌序和洗牌后的牌序,这样每一次操作都可以把start[]的每一个位置的牌号存放在end[]的对应位置中,再用end[]覆盖start[],这样当操作了K轮之后,数组start[]还是存放了最终的牌序;

注意:

  • 末尾的输出不能有空格;
#include<cstdio>

const int N = 54;

int start[N+1],end[N+1];
int next[N+1]; 

char mp[5] = {'S','H','C','D','J'};


int main(){

    int k;
    scanf("%d",&k);

    for(int i=1;i<=N;i++){
        scanf("%d",&next[i]);
    }

    for(int i=1;i<=N;i++){
        start[i] = i;
    }

    for(int step=0;step<k;step++){
        for(int i=1;i<=N;i++){
            end[next[i]] = start[i];
        }
        for(int i=1;i<=N;i++){
            start[i] = end[i];
        }
    }

    for(int i=1;i<=N;i++){
        if(i!=1){
            printf(" ");
        }

        int t = start[i] - 1;

        printf("%c%d",mp[t/13],t%13+1);

    }


    return 0;
}