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 }

 

你可能感兴趣的:(poj)