A1042.Shuffling Machine(20)

题目描述:

Shuffling is a procedure used to randomize a deck of playing cards. Because standard shuffling techniques are seen as weak, and in order to avoid "inside jobs" where employees collaborate with gamblers by performing inadequate shuffles, many casinos employ automatic shuffling machines. Your task is to simulate a shuffling machine.

The machine shuffles a deck of 54 cards according to a given random order and repeats for a given number of times. It is assumed that the initial status of a card deck is in the following order:

S1, S2, ..., S13, H1, H2, ..., H13, C1, C2, ..., C13, D1, D2, ..., D13, J1, J2

where "S" stands for "Spade", "H" for "Heart", "C" for "Club", "D" for "Diamond", and "J" for "Joker". A given order is a permutation of distinct integers in [1, 54]. If the number at the i-th position is j, it means to move the card from position i to position j. For example, suppose we only have 5 cards: S3, H5, C1, D13 and J2. Given a shuffling order {4, 2, 5, 3, 1}, the result will be: J2, H5, D13, S3, C1. If we are to repeat the shuffling again, the result will be: C1, H5, S3, J2, D13.

输入格式:

Each input file contains one test case. For each case, the first line contains a positive integer K (<= 20) which is the number of repeat times. Then the next line contains the given order. All the numbers in a line are separated by a space.

输出格式:

For each test case, print the shuffling results in one line. All the cards are separated by a space, and there must be no extra space at the end of the line.

输入样例:

2
36 52 37 38 3 39 40 53 54 41 11 12 13 42 43 44 2 4 23 24 25 26 27 6 7 8 48 49 50 51 9 10 14 15 16 5 17 18 19 1 20 21 22 28 29 30 31 32 33 34 35 45 46 47

输出样例:

S7 C11 C10 C12 S1 H7 H8 H9 D8 D9 S11 S12 S13 D10 D11 D12 S3 S4 S6 S10 H1 H2 C13 D2 D3 D4 H6 H3 D13 J1 J2 C1 C2 C3 C4 D1 S5 H5 H11 H12 C6 C7 C8 C9 S2 S8 S9 H10 D5 D6 D7 H4 H13 C5


题目翻译:

洗牌是一个打乱一副扑克牌的过程。因为标准的洗牌过程被视为弱点,并且为了避免赌场员工与赌徒进行的“内部合作”,许多赌场使用自动洗牌机。你的任务是模拟一个自动洗牌机。

这个机器按照随机顺序打乱54张牌,并重复这个过程N次(N为输入的次数)。假定卡牌的初始状态如下所示:

S1, S2, ..., S13, H1, H2, ..., H13, C1, C2, ..., C13, D1, D2, ..., D13, J1, J2

其中:

  • 梅花 C
  • 黑桃 S
  • 红桃 H
  • 方块 D
  • 王牌 J

给定的顺序是[1,54]中不同整数的置换。如果第i个位置的数字是j,那么意味着把这张卡从位置i移动到位置j

举例说明:

假如现在我们只有五张卡:S3,H5 C1 D13 J2

给出一个洗牌顺序{4,2,5,3,1}

洗牌的结果为:J2 H5 D13 S3 C1

若再次执行这个顺序

则洗牌的结果为:

C1 H5 S3 J2 D13

输入格式:

第一行输入重复次数(小于等于20)

第二行输入给定的顺序

输出格式:

将洗牌结果打印在一行 空格隔开 行末不得有额外的空格

思路分析:

首先我们可以看到初始顺序是按照S1-13 H1-13 C1-13 D1-13 J1 J2排列的

这样就得到了【1,54】中每个数字与每张牌的对应关系如下:

  • S   1-13
  • H  14-26
  • C   27-39
  • D   40-52
  • J   53、54

我们不妨设一个char数组表示颜色:

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

假设牌号为x(1<=x<=54)

那么(x-1)/13的结果则为花色对应的下标

(x-1)%13+1的结果则为所属花色下的牌号

我们现在假想只进行一次打乱操作:

原来的顺序是1 2 3 4 5..........54

给出的顺序是36 52 37 38 3 39.......47

那么操作非常简便:

建立一个int[55]数组 对应下标存储原始牌号 这样除了0下标 每一个下标均对应初始的牌号

然后从下标1开始 读取54个给出的数字覆盖原数组

这样这个int[55]数组就成为了 0  36  52  37  38.......

然后我们只需要从下标1开始按照花色与牌号对应关系打印出对映的牌

一次打乱操作与多次打乱操作的不同:

现在进行了一次打乱之后我们有这样一个int[55]数组:

0  36  52  37  38.......

那么此时我们需要进行第二次打乱操作

又输入了36  52  37  38.......这54个数

这次因为我们目前的数组已经是乱序了 不能再次进行简单的覆盖操作

而是需要根据下标进行查找

比如一轮打乱后首位是36 第36号牌是C10

此时要将这张C10从第一位再次换到36位 那么需要把这个数组中的第36号元素(的值)换成36

所以我们一共需要3个数组来进行这一系列操作



总结一下每一次打乱分为以下几步:

A数组存储原始排序 B数组存储输入的顺序 C数组为临时数组 这三个数组均假设从下标1开始

1.C[B[i]]=A[i]

给C数组的第B[i]个元素赋值A元素的对应值

举例说明:i=10 输入的第十个顺序元素为 30 原始排序中第十个元素为10

此时将临时数组的第30个元素的值存为10

这样如果只进行一次洗牌

按照下标遍历临时数组 当遍历到第30个元素的时候 读出的值为10 就相当于将原来的10号牌放到了第三十位

如果再进行洗牌 进行第二步操作:

2.A[i]=C[i]

此时A数组所存储的最初顺序已经不起作用

而此时刚才完成转换的C数组 就相当于这一次转换的“原始数组”


第三步:

3.按照格式输出


AC代码:

#include <stdio.h>
#include <stdlib.h>
char color[5]={'S','H','C','D','J'};
int start[55],order[55],end[55];
int main()
{
  int time=0; //输入需要打乱的次数
  scanf("%d",&time);
  for(int i=1;i<55;i++)
  {
      start[i]=i;  //初始化start数组 用1-54对应牌号
  }
  for(int i=1;i<55;i++)
  {
      scanf("%d",&order[i]); //输入打乱顺序
  }
  for(int j=0;j<time;j++) //总共进行time次打乱
  {
      for(int i=1;i<55;i++)
      {
          end[order[i]]=start[i];//第一步C[B[i]]=A[i]
      }
      for(int i=1;i<55;i++)
      {
          start[i]=end[i]; //第二步:A[i]=C[i]  构建新的原始数组
      }
  }
  for(int i=1;i<55;i++)
  {
      if(i!=1)
      {
          printf(" ");
      }
      start[i]--;
      printf("%c%d",color[start[i]/13],start[i]%13+1);  //第三步 按格式输出

  }
  return 0;
}

注意点:

1.结尾不能有空格

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页