SPOJ 1108 Card Trick 暴力模拟

 解释一下样例,因为我觉得这个题意表述的不是很清楚。以第二组样例为例。

牌序为:3 1 4 5 2

第一轮:把 3 放到末尾:1 4 5 2 3,最顶上的牌是1,把1拿走。剩余 4 5 2 3

第二轮:1.把4放到末尾:5 2 3 4

           2.把5放到末尾:2 3 4 5

           最顶上的牌是2,把 2 拿走,剩余:3 4 5

第三轮:1.把3放到末尾:4 5 3

           2.把4放到末尾:5 3 4

           3.把5放到末尾:3 4 5

          最顶上的牌是3,把 3 拿走,剩余:4 5

第四轮:1.把4放到末尾:5 4

           2.把5放到末尾:4 5

           3.把4放到末尾:5 4

           4.把5放到末尾:4 5

           最顶山的牌是4,把 4 拿走,剩余5

第五轮:5次把5放到末尾的操作,把 5 拿走。操作结束。

方法:仍然以第二组样例为例,

一开始是5个空位:-----

1.从第1个位置开始,数 1 个空格: -1---

2.从放1的位置开始,数 2 个空格:-1--2

3.从放2的位置开始,数 3 个空格:31--2 (若后面没有位置,再从第一个位置开始)

4.从放3的位置开始,数 4 个空格:314-2

5.从放5的位置开始,数 5 个空格:31452

即每次超过最后一个位置时,再返回头一个位置。在每次要放的牌 i 之前数 i 个空格就行。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 
 5 const int MAXN = 20010;
 6 
 7 int n;
 8 int ans[MAXN];
 9 
10 int main()
11 {
12     int T;
13     scanf( "%d", &T );
14     while ( T-- )
15     {
16         scanf( "%d", &n );
17         int cur = 1;
18         int pos = 1;
19         memset( ans, -1, sizeof(ans) );
20         while ( cur <= n )
21         {
22             int i, cnt;
23             int left = n - ( cur - 1 ); //剩余空格的个数
24             left = cur % left + 1;      //一定要取模!!!不然会超时
25             for ( i = pos, cnt = 0; ; ++i )
26             {
27                 if ( i > n ) i = 1;
28                 if ( ans[i] == -1 ) ++cnt;
29                 if ( cnt == left ) break;
30             }
31             ans[i] = cur;
32             pos = i;
33             ++cur;
34         }
35 
36         for ( int i = 1; i <= n; ++i )
37         {
38             if ( i != 1 ) putchar(' ');
39             printf( "%d", ans[i] );
40         }
41         puts("");
42     }
43     return 0;
44 }
原文地址:https://www.cnblogs.com/GBRgbr/p/3210547.html