PAT A1042 Shuffling Machine
Sample Input:
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
Sample Output:
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
word | meaning |
---|---|
shuffling | 洗牌 |
procedure | n. 程序 |
a deck of | 一副(牌) |
inside job | n.内鬼 |
collaborate | vi. 合作、勾结 |
inadquate | 不足 |
casino | n. 赌场 |
permutation | n. (一组事物可能的一种)序列,排列 |
- 思路1:
简单模拟,注意下标变换 - code1:
#include <stdio.h>
#include <iostream>
using namespace std;
int main(){
int cards[55], order[55], tmp[55];
int k;
scanf("%d", &k);
for(int i = 1; i < 55; ++i){
scanf("%d", &order[i]);
cards[i] = i;
}
//可以和上一个循环合并!
// for(int i = 1; i < 55; ++i){
// scanf("%d", &order[i]);
// //scanf("%d "); //!!!:WRONG 1 不能加空格
// }
while(k > 0){
for(int i = 1; i < 55; ++i){
//排序一次
tmp[order[i]] = cards[i];
}
for(int i = 1; i < 55; ++i){
cards[i] = tmp[i];
}
k--;
}
//输出结果:
char a[6] = {'S', 'H', 'C', 'D', 'J'}; //!!!:TIPS 1
for(int i = 1; i < 55; ++i){
// if(cards[i] % 13 != 0) printf("%c%d ", a[(cards[i]-1)/13], cards[i]%13);
// else printf("%c13 ", a[cards[i]/13]); //!!!WRONG 2 13/13=1跳到下一组了
//优化:不需要if_else:(x-1)%13+1就是对应的牌序
printf("%c%d", a[(cards[i]-1)/13], (cards[i] - 1)%13 + 1);
if(i != 54) printf(" ");
}
return 0;
}
- TIPS 1:
直接用字符串赋值char数组,节省敲键盘时间
char a[7] = {"SHCDJ"};
-
TIPS 2:
应注意:本题数组cards[]
等的存储,是从下标1开始的,而数组a[]
是从0开始存储的,所以做除法和取模运算边界情况会出错,所以应先-1转化为从0开始,求出来的才是a[]中对应下标 -
思路2:
直接求出最终order[]:洗一次牌,card i
的位置是ord[i]
,洗2次是ord[ord[i]]
…洗k次:ord[ord[...ord[i]]]
,可以用递归或迭代求出每个牌i的最终位置;
(不好, 麻烦!) -
code:
#include <bits/stdc++.h>
using namespace std;
vector<int> ord(55), nex(55), fin(55);
char s[7] = "SHCDJ";
//void deal(int k){
// for(int i = 1; i <= 54; ++i){
// int next = ord[i], cnt = k; ///迭代版
// while(--cnt){
// next = ord[next];
// }
// nex[i] = next;
// }
//}
int Nex(int i, int deep, int k){ //递归版
if(deep >= k) return ord[i];
i = Nex(ord[i], deep+1, k);
}
void deal(int k){
for(int i = 1; i <= 54; ++i){
nex[i] = Nex(i, 1, k);
}
}
int main(){
int k;
scanf("%d", &k);
for(int i = 1; i <= 54; ++i){
scanf("%d", &ord[i]);
}
deal(k);
for(int i = 1; i <= 54; ++i){
fin[nex[i]] = i;
}
for(int i = 1; i <= 54; ++i){
int num = (fin[i] - 1) % 13 + 1;
int s_id = (fin[i] -1) / 13;
printf("%c%d", s[s_id], num);
if(i != 54) printf(" ");
}
return 0;
}
- 改成DFS的思路:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 55;
char sign[6] = "SHCDJ";
int DFS(int order[], int id, int dep, int times)
{
if(dep == times)
{
return order[id];
}
DFS(order, order[id], dep + 1, times);
}
int main()
{
int n, order[maxn], end_pos[maxn];
scanf("%d", &n);
for(int i = 1; i <= 54; ++i)
{
scanf("%d", &order[i]);
}
for(int i = 1; i <= 54; ++i)
{
int end_p = DFS(order, i, 1, n);
end_pos[end_p] = i;
}
for(int i = 1; i <= 54; ++i)
{
char tsign = sign[(end_pos[i] - 1) / 13];
int tend = (end_pos[i] - 1) % 13 + 1;
printf("%c%d", tsign, tend);
if(i < 54) printf(" ");
}
return 0;
}