有一个数列a1,a2,a3,…an.每次可以从中任意选三个相邻的数ai-1,ai,ai+1,进行如下操作(此操作成为“ai进行操作”)
(ai-1,ai,ai+1)→(ai-1+ai,-ai,ai+ai+1)
给定初始序列和目标序列,是否能通过以上操作,将初始序列转换为目标序列?例如,初始序列(1,6,9,4,2,0),目标序列(7,-6,19,2,-6,6)可以经过如下操作:
(1 6 9 4 2 0)→ (1 6 13 -4 6 0)→(1 6 13 2 -6 6)→(7 -6 19 2 -6 6)加下划线的是每次被操作的ai。
如果初始序列是(1 2 3)目标序列是(1 3 2)。那么无论如何也不能通过这种操作从初始序列转换到目标序列。
任务:输入初始序列和目标序列,输出yes或no(能否转换)。
static int[,] a = new int[3, 100];
static int n;
static void Main(string[] args)
{
int x, i;
bool tf;
Console.WriteLine("请输入初始数列的长度:");
n = int.Parse(Console.ReadLine().Trim());
Console.WriteLine("请输入初始序列:");
for (i = 1; i <= n; i++)//计算初始序列的部分和
{
x = int.Parse(Console.ReadLine().Trim());
a[1, i] = a[1, i - 1] + x;
}
Console.WriteLine("请输入目标序列:");
for (i = 1; i <= n; i++)//计算目标序列的部分和
{
x = int.Parse(Console.ReadLine().Trim());
a[2, i] = a[2, i - 1] + x;
}
if (a[1, n] != a[2, n])//若初始序列和目标序列的数和不同,则失败退出
{
Console.WriteLine("NO");
return;
}
qsort(1, 1, n);//按照递增排列初始序列和目标序列
qsort(2, 1, n);
tf = false;//失败标志初始化
for (i = 1; i <= n; i++)//顺序搜索初始序列和目标序列的每一个对应位置,一旦有不同数字,失败退出,如果都相同,成功退出
{
if (a[1, i] != a[2, i])
{
tf = true;
break;
}
}
if (tf)
Console.WriteLine("NO");
else
Console.WriteLine("YES");
}
static void qsort(int d, int p, int r)//按照递增顺序快速排列初始序列(d=1)和目标序列(d=2)
{
int i, j, x;
if (p < r)
{
Random rand = new Random();
x = a[d, p + rand.Next(r - p + 1)];//随机取出a[d]中的一个元素值
i = p - 1; j = r + 1;//设左右指针
while (true)//移动左右指针,使得左子区间a[d,p..i]中的每个元素值小于等于右子区间a[d,i+1..r]的元素值
{
do
--j;
while (a[d, j] <= x&&j>0);
do
++i;
while (a[d, i]>=x&&i<n);
if (i < j)
{
a[d, 0] = a[d, i];//交换a[d,i]和a[d,j]
a[d, i] = a[d, j];
a[d, j] = a[d, 0];
}
else break;
}
qsort(d, p, j);//分别递归左子区间和右子区间
qsort(d, j + 1, r);
}
}