传送门UVa 120 - Stacks of Flapjacks
题意是给你一串数字, 可以选择一个位置翻转, 但是底部的数字不能变, 要求让你输出直到数字排成从小到大的每一步骤所代表的数字.
一开始准备把输入变成字符串, 然后直接一个strrev就翻转了, 方便快捷....直到后来写完了, 代入测试数据的时候才发现这样做是错的.如果输入40的话翻一下就变成04了, 然后我又瞬间想到前几天C++课堂测验也是叫我们翻转一个数组, 我就用这种方法写了
(╯‵□′)╯ ┴─┴
没办法, 只好把字符串改为数组, 好在其他地方不用什么大改, 加一个反转的函数就可以了.
这题的算法一开始也想了很久. 说起来也很简单, 我的想法是另外建一个数组, 按照从小到大排序, 之后一个数字一个数字和原数组对照起来, 如果在位置 i 不同的话就翻转一下, 如果翻转一下还是不同, 再翻回来, 找到那个数字, 翻一下, 再翻一下位置 i .以此类推, 直到扫描完一遍数组. 程序结束.
因为我一开始是用strrev做的, 为了函数的方便使用, 我就把原数组翻转了一下, 把目标数组也翻转了一下. 这里请大家无视....
PS:做完这题已经晚上12点了, 提交了一下, 等了5分钟, 还是没有结果. 果断上床了...但是不知道结果根本睡不着, 于是用手机颤抖着打开UVa, 点开My Submission...当我看到那七个字母时候的感觉...真是...爽啊...终于可以睡好觉了..
#include <cstdio>
#include <cstdlib>
#include <cstring>
int temp[100];
int num[100];
int comp(const void *_a, const void *_b)
{
int *a = (int *)_a;
int *b = (int *)_b;
return *b - *a;
}
void Rev(int i, int k)
{
int k1 = k - 1; //k1为数组最大下标
int i1 = i;
for (int l = 0; l < (k - i) / 2; l++)
{
int a = temp[i1];
temp[i1++] = temp[k1];
temp[k1--] = a;
}
}
int main()
{
//freopen("input.txt", "r", stdin);
int i, j;
int flag;
char ch;
int k;
while (scanf("%d%c", &temp[0], &ch) == 2)
{
k = 1;
while (ch != '\n')
scanf("%d%c", &temp[k++], &ch);
int cnt = 1;
int fflag = 0;
for (i = 0; i < k; i++)
{
if (fflag == 1)
printf(" ");
printf("%d", temp[i]);
fflag = 1;
}
printf("\n");
Rev(0, k);
for (i = 0; i < k; i++) //转移元素
num[i] = temp[i];
qsort(num, k, sizeof(num[0]), comp); //num为排序后的数组.
for (i = 0; i < k; i++)
{
if (temp[i] != num[i]) //目标序列为54321, 从头开始搜索.
{
flag = 0;
Rev(i, k); //翻一下对应位置.
if (temp[i] != num[i]) //如果翻过来不相等, 翻回去
Rev(i, k);
else //如果翻过来相等, 输出位置
{
printf("%d ", i + 1);
flag = 1;
}
if (flag == 0) //如果翻一下没找到, 找到目标数字, 翻一下, 再从当前位置开始翻
{
for (j = i; j < k; j++)
{
if (temp[j] == num[i])
{
Rev(j, k);
printf("%d ", j + 1);
i--;
break;
}
}
}
}
}
printf("0\n");
}
return 0;
}