题目详情
小强有 3 个箱子 A,B,C 用来装书,所有的书(一共n本)都按序号由小到大的顺序堆在 A上,现在他想把所有的书全都放到 C 里面去。每次他从 A 书架拿 a 本书(不够就全拿完)到 B,A 箱子翻转,然后从 B 拿 b 本书(不够就全拿完)到
C,B 箱子翻转。然后重复操作,直到所有书都到了 C,求最后的C 里面书的顺序,详细见样例。
输入描述:
输入由多组数据构成,每组数据占一行,3 个数,n(1<=n<=10^5),a(1<=a<=10^9) , b(1<=b<=10^9),含义见题目表述。以文件结尾。
输出描述:
每组数据输出一行,首先输出数据组数,然后输出 n 个数,C 中书的排列。
答题说明
输入样例:
4 2 1
输出样例
Case 1: 1 4 2 3
Hint
初始状态A:4321 B: 空 C:空
第一次: A->B A:21 B:34 C: 空
A 翻转 A:12 B:34 C: 空
B->C A:12 B: 4 C: 3
B 翻转 A:12 B:4 C: 3
第二次: A->B A:空 B:214 C:3
A 翻转 A:空 B:214 C:3
B->C A:空 B:14 C:23
B 翻转 A:空 B:41 C:23
第三次: B->C A:空 B:1 C:423
B 翻转 A:空 B:1 C:423
第四次: B->C A:空 B:空 C:1423
思路:这道题用双向链表来做就再适合不过了,因为A和B都有翻转操作,而双向链表可以从两个方向遍历链表元素,所以当翻转之后就相当于从另一个方向取链表元素。最终,用两个双向链表代表A和B,用一个栈代表C,一直模拟题目操作,当A和B都为空的时候,输出栈C的值即可。
代码:
#include<iostream> #include<list> #include<stack> using namespace std; int main() { int n, a, b, n_case = 0; while(cin >> n) { n_case++; cin >> a >> b; list<int> a_list;//存A的元素 list<int> b_list;//存B的元素 stack<int> s;//存C的元素 for(int i = 1; i <= n; i++) a_list.push_front(i);//先用1-n装满A int count = 1; while(!(a_list.empty() && b_list.empty())) { int a_tmp = a; int b_tmp = b; if(count % 2 == 1)//奇数次操作的时候从链表的头部front取元素 { while((!a_list.empty()) && a_tmp--) { b_list.push_front(a_list.front());//取A的前a元素 a_list.pop_front(); } while((!b_list.empty()) && b_tmp--) { s.push(b_list.front());//取B的前b元素 b_list.pop_front(); } } else//偶数次操作的时候从尾部取元素 { while((!a_list.empty()) && a_tmp--) { b_list.push_back(a_list.back()); a_list.pop_back(); } while((!b_list.empty()) && b_tmp--) { s.push(b_list.back()); b_list.pop_back(); } } count++; } cout << "Case " << n_case << ":"; while(!s.empty()) { cout << ' ' << s.top(); s.pop(); } cout << endl; } return 0; }