问题描述
在想象中的土地上,如果人们面对面,他们就有能力互相传送。我应该编写一个算法来找出根据输入进行多少次隐形传送。如果有 1 表示此人面向右侧,如果有 2 则表示此人面向左侧。
第一行是一个数字N,这片土地上的人数。 第二行有N个数字,1或2。
Input Output
3 2
1 2 2
Input Output
4 0
2 2 1 1
这是我的代码,但是当一个面朝右的人遇到一个面朝左的人时,他们会相互传送,但算法不会检查是否有更多的人面朝第一个人身后。
int main()
{
int n,a,teleportiranja = 0;
cin >> n;
int niza[n];
for (int i = 0; i < n; i++)
{
cin >> a;
niza[i] = a;
}
for (int x = 0; x < n; x++)
{
if (niza[x] == 1 && niza[x + 1] == 2)
{
swap(niza[x],niza[x + 1]);
teleportiranja++;
}
}
cout << teleportiranja << endl;
return 0;
}
解决方法
您确实检查了第一个人后面的人,但是在检查了所有人一次之后,您就停下来了。您需要第二个循环来不断检查传送,直到找不到其他传送为止。像这样:
#include <iostream>
using namespace std;
int main() {
int n,a,teleportiranja = 0;
cin >> n;
int niza[n];
for (int i = 0; i < n; i++) {
cin >> a;
niza[i] = a;
}
bool required_teleports;
do {
for (int x = 0; x < n; x++) {
required_teleports = false;
if (niza[x] == 1 && niza[x + 1] == 2) {
swap(niza[x],niza[x + 1]);
teleportiranja++;
required_teleports = true;
}
}
} while (required_teleports);
cout << teleportiranja << endl;
return 0;
}
,
每个面朝左边的人(值 2)都必须超过他前面的所有面朝右面的人(值 1)。因此,如果我们选择任何值为 2 的人,他将传送的数量等于在他之前的值为 1 的人的数量。这可以通过跟踪 1 的数量在 O(n) 时间内通过单个循环完成far,当我们达到 2 时,我们将当前 1 的数量添加到传送总数中。
int main() {
int n;
cin >> n;
int ones = 0;
int cnt = 0;
for (int i = 0; i < n; i++)
{
int a;
cin >> a;
if (a == 1)
ones++;
else cnt += ones;
}
cout << cnt << endl;
return 0;
}