Очевидно, что задачу минимизации заданной суммы можно свести к двум
подзадачам: для x и для y. Рассмотрим одномерную задачу для x.
По заданным x1, x2, ..., xn найти
x, такое что s(x) = |x - x1| + |x - x2| + ... +
|x - xn| минимально. Пусть x - точка, в которой s(x) достигает
минимума. Пусть слева от нее k1 точек, а справа k2 точек. Если k1 < k2, то,
сдвинувшись на небольшое расстояние вправо, мы уменьшим s(x), поэтому k1 >= k2.
Аналогично k1 <= k2. В результате получаем, что k1 = k2. Таким образом,
искомая точка - это точка, слева и справа от которой одинаковое количество точек
из заданного набора. В случае когда n нечетно x = x(n+1)/2, а когда
n четно в качестве x можно взять любую точку из отрезка [xn/2,
xn/2+1].
Текст программы:
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int n, x1, y1, i;
vector<int> x, y;
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
scanf("%d", &n);
for (i = 0; i < n; i++)
{
scanf("%d%d", &x1, &y1);
x.push_back(x1);
y.push_back(y1);
}
sort(x.begin(), x.end());
sort(y.begin(), y.end());
printf("%d.0000 %d.0000\n", x[(n-1) / 2], y[(n-1) / 2]);
fclose(stdout);
return 0;
}
Результаты по задаче №7 "Манхеттен" (5 баллов).
Ник
Результат
ak13_boda
accepted
aleksandrr
accepted
arti
accepted
Berdan
accepted
DEathkNIghtS
accepted
SadKo_Sobaka
time limit exceeded on test #7
VOLAND
accepted
Решение задачи №8 "Морской бой" (10 баллов).
Данная задача скорее не алгоритмическая, а задача на аккуратную реализацию.
Поэтому просто помещаю текст решения.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max(a, b) (((a) > (b)) ? (a) : (b))
typedef char tfield[10][11];
typedef int tshot[10][10];
void show_mes(char *mes)
{
printf("%s\n", mes);
exit(0);
}
void input_field(tfield &f)
{
for (int i = 0; i < 10; i++)
scanf("%s", f[i]);
}
int test_field(tfield &f)
{
int i, j;
int m[10][10], c[6];
for (i = 0; i < 9; i++)
for (j = 0; j < 9; j++)
{
if (f[i][j] == '#' && f[i+1][j+1] == '#') return 0;
if (f[i][j+1] == '#' && f[i+1][j] == '#') return 0;
}
m[0][0] = (f[0][0] == '#') ? 1 : 0;
for (i = 1; i < 10; i++)
{
if (f[0][i] == '.') m[0][i] = 0;
else m[0][i] = 1 + m[0][i - 1];
if (f[i][0] == '.') m[i][0] = 0;
else m[i][0] = 1 + m[i - 1][0];
}
for (i = 1; i < 10; i++)
for (j = 1; j < 10; j++)
if (f[i][j] == '.') m[i][j] = 0;
else m[i][j] = 1 + max(m[i - 1][j], m[i][j - 1]);
c[5] = 0;
for (i = 4; i > 0; i--) c[i] = (5 - i) + c[i + 1];
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
if (m[i][j] > 4) return 0;
else if (m[i][j] > 0) c[m[i][j]]--;
for (i = 1; i <= 4; i++)
if (c[i]) return 0;
return 1;
}
void recur(int &killed, tfield &f, tshot &s, int r, int c, int dr, int dc)
{
if (r < 0 || r >= 10 || c < 0 || c >= 10) return;
if (f[r][c] != '#') return;
if (!s[r][c]) killed = 0;
else recur(killed, f, s, r + dr, c + dc, dr, dc);
}
void main()
{
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
tfield f1, f2;
int n, i, curpl, ships1, ships2;
char str[200];
tshot shot1, shot2;
input_field(f1);
if (!test_field(f1))
show_mes("Error: first player's field is incorrect");
input_field(f2);
if (!test_field(f2))
show_mes("Error: second player's field is incorrect");
curpl = 1;
ships1 = ships2 = 10;
scanf("%d", &n);
memset(shot1, 0, sizeof(shot1));
memset(shot2, 0, sizeof(shot2));
for (i = 0; i < n; i++)
{
if (ships1 == 0 || ships2 == 0)
{
sprintf(str, "Error in move #%d: the game is already finished", i + 1);
show_mes(str);
}
int pl, r, c;
char pos[3], ans[10];
scanf("%d%s%s", &pl, pos, ans);
if (pl != curpl)
{
sprintf(str, "Error in move #%d: this move must be made by another player", i + 1);
show_mes(str);
}
r = pos[0] - 'a';
c = pos[1] - '0';
if (pl == 1)
{
if (shot1[r][c])
{
sprintf(str, "Error in move #%d: two shots in one place", i + 1);
show_mes(str);
}
shot1[r][c] = 1;
int killed = 0;
if (f2[r][c] == '#')
{
killed = 1;
recur(killed, f2, shot1, r - 1, c, -1, 0);
recur(killed, f2, shot1, r + 1, c, +1, 0);
recur(killed, f2, shot1, r, c - 1, 0, -1);
recur(killed, f2, shot1, r, c + 1, 0, +1);
}
if (f2[r][c] == '.' && strcmp(ans, "past") ||
f2[r][c] == '#' && !killed && strcmp(ans, "wounded") ||
f2[r][c] == '#' && killed && strcmp(ans, "killed"))
{
sprintf(str, "Error in move #%d: wrong enemy's answer", i + 1);
show_mes(str);
}
if (killed) ships2--;
if (f2[r][c] == '.') curpl = 2;
}
else
{
if (shot2[r][c])
{
sprintf(str, "Error in move #%d: two shots in one place", i + 1);
show_mes(str);
}
shot2[r][c] = 1;
int killed = 0;
if (f1[r][c] == '#')
{
killed = 1;
recur(killed, f1, shot2, r - 1, c, -1, 0);
recur(killed, f1, shot2, r + 1, c, +1, 0);
recur(killed, f1, shot2, r, c - 1, 0, -1);
recur(killed, f1, shot2, r, c + 1, 0, +1);
}
if (f1[r][c] == '.' && strcmp(ans, "past") ||
f1[r][c] == '#' && !killed && strcmp(ans, "wounded") ||
f1[r][c] == '#' && killed && strcmp(ans, "killed"))
{
sprintf(str, "Error in move #%d: wrong enemy's answer", i + 1);
show_mes(str);
}
if (killed) ships1--;
if (f1[r][c] == '.') curpl = 1;
}
}
if (!ships2)
show_mes("OK: first player is winner");
else if (!ships1)
show_mes("OK: second player is winner");
else
show_mes("OK: the game isn't finished yet");
}
Результаты по задаче №8 "Морской бой" (10 баллов).
Ник
Результат
ak13_boda
wrong answer on test #2
aleksandrr
accepted
arti
wrong answer on test #4
Berdan
accepted
DEathkNIghtS
accepted
SadKo_Sobaka
wrong answer on test #9
VOLAND
wrong answer on test #17
Условия задач, тесты и решения вы всегда можете
найти на сайте accepted.narod.ru.
Ведущий рассылкой: Виктор Журавлев
Вопросы, пожелания, предложения пишите на мой
e-mail.