数组左旋转k位 std::rotate() POJ 1978

来源:互联网 发布:温州网络学堂注册 编辑:程序博客网 时间:2024/06/07 20:26


题意:模拟一个洗牌操作。先输入两个正整数N和R,N表示有N张牌,R表示有R次操作。然后再是有R行,每行有两个正整数p和c,表示从p开始数起c张要放到牌顶。现在问你:经过R次操作后,这N张牌的首张牌是什么数字?
注意:牌的数字是倒着排列的。
样例解释1:
5 2 //5张牌 2次洗牌 当前序列:5 4 3 2 1
3 1//从第三张牌数起 到 第四张牌 要放到牌顶。(注意:这里有一个数字放到牌顶,那就是3)当前序列:3 5 4  2 1
3 1//当前序列:4 3 5 2 1
输出:
4


样例解释2:
10 3//10张牌 3次洗牌 当前序列:10 9 8 7 6 5 4 3 2 1
1 10//从第一张牌数起 到 第十张牌 要放到牌顶(注意: 这里就相当于没有对原牌堆进行操作)当前序列:10 9 8 7 6 5 4 3 2 1
10 1//从第十个数字数起 到 第十一张 要放到牌顶(注意:这里是将第10个数字到第10个数字放到牌顶,只有1张牌) 当前序列:1 10 9 8 7 6 5 4 3 2
8 3//从第八张牌数起 到 第十一张 要放到牌顶 (注意:这里是将第8个数字到第10个数字放到牌顶) 当前序列:
4 3 2 1 10 9 8 7 6 5
输出:

4



思路:直接模拟会比较麻烦,要会两种std函数的方法:

法一:直接用rotate模拟

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <set>#include <queue>#include <map>using namespace std;typedef long long ll;const int N = 123;int a[N];int main() {int n, Q;while(~scanf("%d%d", &n, &Q)) {if(n == Q && n == 0) break;for(int i = 1; i <= n; i++) a[i] = n - i + 1;while(Q --) {int p, c;scanf("%d%d", &p, &c);rotate(a + 1, a + p, a + p + c); }printf("%d\n", a[1]);}}


法二:要是不会rotate函数, 就用reverse, 一次旋转等于三次reverse


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <set>#include <queue>#include <map>using namespace std;typedef long long ll;const int N = 123;int a[N];int main() {int n, Q;while(~scanf("%d%d", &n, &Q)) {if(n == Q && n == 0) break;for(int i = 1; i <= n; i++) a[i] = n - i + 1;while(Q --) {int p, c;scanf("%d%d", &p, &c);reverse(a + 1, a + p + c);reverse(a + 1, a + 1 + c);reverse(a + 1 + c, a + p + c);}printf("%d\n", a[1]);}}


0 0