Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы




Скачать 161.19 Kb.
НазваниеЗадача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы
Дата публикации13.02.2014
Размер161.19 Kb.
ТипЗадача
uchebilka.ru > Военное дело > Задача
ЖАДНЫЕ АЛГОРИТМЫ
Приводится определение жадного алгоритма и описывается принцип жадного выбора. Описывается свойство оптимальности для подзадач. Рассматривается набор олимпиадных задач, которые решаются при помощи жадных алгоритмов.
Рассмотрим некоторую страну U, в денежной системе которой имеются монеты номиналом 1, 2, 5, 10, 25, 50 и 100 копеек. Представьте, что у Вас есть копилка с достаточно большим количеством монет каждого номинала. Вы хотите приобрести ручку стоимостью 82 копейки, заплатив продавцу указанную сумму наименьшим количеством монет.

Очевидно, что для этого сначала необходимо взять монету наибольшего номинала, не большего 82. То есть 50 копеечную монету. После этого остается выплатить 82 – 50 = 32 копейки. Снова берем монету наибольшего номинала, не большего 32. То есть 25 копеечную монету. Остается заплатить 32 – 25 = 7 копеек. Следуя описанной логике, 7 копеек выплачиваем двумя монетами: 5 копеек и 2 копейки.

Итак, за ручку стоимостью 82 копейки мы отдали по одной монете разных номиналов: 50, 25, 5 и 2 копейки (50 + 25 + 5 + 2 = 82).
Жадным алгоритмом называется такой метод решения задачи, в котором изначально выбирается оптимальное решение для некоторой ее части. Далее строится последовательность подзадач, в каждой из которых находится локальный оптимум. При этом последовательность решений задач локальных оптимумов ведет к нахождению глобального оптимума.
Глобальный оптимум выше описанной задачи состоит в нахождении набора наименьшего количества монет с заданной суммой s. Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы p. Таким образом говорят, что приведенная задача решается методом жадного выбора.
Принципиальное преимущество жадных алгоритмов состоит в простоте их понимания и реализации. В их основе лежит принцип нахождения на каждом шаге оптимального решения.
^ 1. Пассажирский лифт. Лифт может поднять не более M кг. В очереди стоят n человек, для каждого из которых известен его вес: a1, a2, …, an. Найти максимальное число людей, которое может уехать на лифте за один раз.

Решение. Элементарной подзадачей является помещение в лифт одного человека. Если имеется несколько кандидатов на помещение в лифт, то оптимальным выбором будет человек с наименьшим весом, так как при этом остается наибольший запас по грузоподъемности. Для решения задачи следует отсортировать веса людей по возрастанию и помещать их в лифт, начиная с самого легкого, до тех пор, пока это возможно.
^ 2. Продажа молока. У компании по продаже молока имеется M поставщиков. Известно, что i -ый поставщик может продать не более ai литров молока по цене pi гривен за литр. За какую наименьшую сумму компания сможет закупить n литров молока?

Решение. Очевидно, что на каждом шаге следует закупать молоко у поставщика с наименьшей ценой. Следует отсортировать поставщиков по цене молока и начинать закупку молока с самого дешевого.
^ 3. Выбор заявок. Имеются n заявок на проведение занятий в одной аудитории. Два разные занятия не могут пересекаться во времени. Каждая заявка содержит время начала ai и время окончания bi занятия. Необходимо найти максимально возможное количество заявок, которое можно удовлетворить.

Вход. Каждая входная строка содержит время начала и конца заявки [ai, bi], i = 1, 2. , … .

Выход. Вывести максимально возможную последовательность заявок, которую можно удовлетворить.

Пример входа

Пример выхода

3 4

2 3

1 6

3 4

2 3

5 8

7 10

9 10

5 8




4 9




9 10





^ 4. Печать открыток [Саратов 259]. Необходимо напечатать n открыток на одном принтере. Время печати открытки рано ti, а время ее доставки – li. Количество курьеров для доставки открыток неограниченно. За какое наименьшее время можно напечатать и доставить все открытки?

Вход. Первая строка содержит количество открыток n (1  n  100). Вторая строка содержит время печати открыток ti (1  in). В третьей строке содержится время доставки открыток li (1  in). Известно, что 1  ti, li  1000.

Выход. Вывести наименьшее время, за которое можно напечатать и доставить все открытки.

Пример входа

Пример выхода

4

192

5 2 11 100




30 100 1 90




^ 5. Оптимальное слияние. Имеются n отсортированных неубывающих последовательностей. Необходимо слить их в одну неубывающую последовательность, минимизируя количество операций чтения-записи. За один шаг разрешается слить только две последовательности. При слиянии двух последовательностей x[1...l1] и y[1... l2] необходимо выполнить l1 операций чтения элементов последовательности x, l2 операций чтения элементов последовательности y и l1 + l2 операций записи для сохранения слитого отсортированного массива. Таким образом, при слиянии последовательностей x[1... l1] и y[1... l2] необходимо выполнить 2 * (l1 + l2) операций чтения-записи. За какое наименьшее число операций чтения-записи можно слить все n отсортированных неубывающих последовательностей?

Вход. Первая строка содержит количество последовательностей n. Вторая строка содержит длины последовательностей l1, l2, …, ln.

Выход. Вывести минимальное количество операций чтения-записи, за которое можно слить все n отсортированных неубывающих последовательностей.

Пример входа

Пример выхода

7

178

3 6 4 8 1 9 3





^ 6. Планирование производственной линии. Имеются n разных деталей, которые должны пройти последовательную конвейерную обработку на двух машинах. В каждый момент времени каждая машина может обрабатывать только одну деталь. Известно, что ai – время обработки i – ой детали на первой машине, bi – время ее обработки на второй машине. Найти такой порядок обработки деталей, при котором время их обработки будет минимальным.

Вход. Первая строка содержит количество деталей n. Далее следуют n строк, каждая из которых содержит время обработки детали на первом и на втором станке.

Выход. Вывести порядок деталей, при котором время их обработки будет минимальным. Если таких порядков несколько, то вывести один из них.

Пример входа

Пример выхода

5

2 4

3 5

3 5

2 4

7 4

6 3

4 3

7 4

6 3

4 3





^ 7. Игра в игру [Топкодер, раунд 217, дивизион 2, уровень 2]. В компьютерной игре Ваша армия сражается с вражеской. Армии выстраиваются в ряд друг против друга так, что перед каждым Вашим воином стоит воин оппонента. Воины имеют силу, которая выражается натуральным числом. В бою сражаются только воины, которые находятся друг против друга (число воинов обоих армий одинаково). Ваш воин выигрывает, если его сила строго больше силы воина соперника. Известно начальное расположение воинов соперника. Требуется так расставить Ваших воинов, чтобы после окончания боя суммарное значение сил оставшихся в живых с Вашей стороны было максимальным.

Класс: PlayGame

Метод: int saveCreatures(vector you, vector computer)

Ограничения: 1  you[i], computer[i]  1000, размер массивов you и computer не более 50.

Вход. Состав Вашей армии you и армии оппонента computer.

Выход. Наибольшее возможное значение суммы сил оставшихся в живых воинов из Вашей армии.

Пример входа

you

computer

{5, 15, 100, 1, 5}

{5, 15, 100, 1, 5}

{1, 3, 5, 7, 9, 11, 13, 15, 17, 19}

{2, 4, 6, 8, 10, 12, 14, 16, 18, 20}


Пример выхода

120

99
^ 8. Мост [Вальядолид, 10037]. n людей ночью хотят перейти на другой берег реки по мосту. У них есть один фонарь. Двигаться по мосту с фонарем могут не более двух человек. Движение по мосту без фонаря запрещено. Для каждого человека известно время, за которое он пересекает мост. Если по мосту двигаются двое, то время их передвижения равно времени более медленного.

Необходимо вывести минимальное время, за которое все n людей перейдут на другой берег реки, а также последовательность переходов, как указано в примере.

Вход. Первая строка содержит количество тестов, за которой следует пустая строка. Тесты разделены друг от друга пустой строкой. Первая строка каждого теста содержит количество людей n (n  1000). Следующие n строк содержат время переходов людей через мост. Время перехода каждого человека через мост не более 100 секунд.

Выход. Первая строка содержит минимальное время, за которое могут пересечь мост n людей. Далее следует стратегия пересечения моста людьми. Каждая строка стратегии содержит одно или два числа, характеризующие людей, которые с фонарем пересекают мост. При существовании нескольких оптимальных стратегий пересечения реки вывести любую.

Пример входа

Пример выхода

1

17




1 2

4

1

1

5 10

2

2

5

1 2

10





^ 9. Все во всем [Вальядолид, 10340]. По заданным двум строкам определить, является ли последовательность символов первой строки подпоследовательностью второй.

Вход. Каждая строка содержит два слова, состоящих из символов английского алфавита и цифр. Слова разделены пробелом.

Выход. Для каждого теста вывести в отдельной строке слово ‘Yes’ или ‘No’ в зависимости от того, является ли первая строка подпоследовательностью второй.

Пример входа

Пример выхода

sequence subsequence

Yes

person compression

No

VERDI vivaVittorioEmanueleReDiItalia

Yes

caseDoesMatter CaseDoesMatter

No



^ УКАЗАНИЯ И РЕШЕНИЯ
3. Выбор заявок. Упорядочим заявки [ai, bi] по возрастанию их времен окончания: b1b2  …  bn. Первая заявка, которая будет удовлетворена, должна иметь наименьшее время окончания. Если предположить, что это не так, то первую удовлетворенную заявку можно заменить на ту, которая имеет самое раннее время окончания. При этом такая операция замены не нарушит совместность заявок и не изменит их количества. То есть оптимальное решение начинается с жадного выбора. Выбросим все заявки, несовместимые с первой включенной. Далее решаем задачу выбора оптимального набора заявок из множества оставшихся.

Реализация. Заявки, представленные в виде пар (ai, bi), хранятся в векторе пар v в обратном порядке: v[i].first содержит bi, а v[i].second равно ai. Такое хранение удобно, так как функция sort сортирует пары, хранящиеся в векторе, по первой компоненте (заявки сортируются по возраствнию времени их окончания). Рассмотрим j - ую заявку (aj, bj), стоящую после i - ой (ai, bi). В результате сортировки имеет место неравенство: bibj. Заявки (ai, bi) и (aj, bj) не пересекаются, если biaj (время начала j - ой заявки не может быть раньше конца i - ой). После вывода на печать очередной i - ой заявки пропускаем все j - ые заявки (i < jn), не совместные с ней. После чего i - ой становится заявка, которая может быть выполнена после последней выведенной на экран.
#include

#include

#include

using namespace std;
int i, j;

vector
> v;
void main(void)

{

while(scanf("%d %d",&i,&j) == 2) v.push_back(make_pair(j,i));

sort(v.begin(),v.end());

for(i = 0; i < v.size(); i++) printf("%d %d\n",v[i].second,v[i].first);

printf("Result:\n");

for(i = 0, j = 1; i < v.size(); i = j, j = i + 1)

{

printf("%d %d\n",v[i].second,v[i].first);

while((j < v.size()) && (v[j].second < v[i].first)) j++;

}

}
^ 4. Печать открыток [Саратов 259]. Отсортируем открытки по невозрастанию времени доставки: l1l2 …  ln. В этой последовательности будем печатать и сразу же доставлять открытки. Время доставки i - ой открытки равно + li (до этого следует напечатать открытки с номерами 1, 2, ..., i и потратить время li на доставку). Таким образом, минимальное время выполнения всей работы равно

(+ li)

Реализация. Информацию об открытках (ti, li) храним в векторе пар v. Открытки сортируем по убыванию времени доставки при помощи функции f. Вычисляем требуемое минимальное время согласно выше приведенной формуле.
#include

#include

#include

using namespace std;
int t[101],l;

vector
> v;
int f(pair x, pair y)

{

return (x.second > y.second);

}
void main(void)

{

int n, i, sum, max;

scanf("%d",&n);

for(i = 0; i < n; i++) scanf("%d",&t[i]);

for(i = 0; i < n; i++)

{

scanf("%d",&l);

v.push_back(make_pair(t[i],l));

}

sort(v.begin(),v.end(),f);

sum = max = 0;

for(i = 0; i < n; i++)

{

sum += v[i].first;

if (sum + v[i].second > max) max = sum + v[i].second;

}

printf("%d\n",max);

}
^ 5. Оптимальное слияние. На каждом шаге следует сливать две последовательности наименьшей длины.

Реализация. Длины последовательностей храним в мультимножестве s, так как некоторые последовательности могут иметь одинаковую длину. На каждом шаге следует извлекать два наименьших числа (они всегда находятся в начале множества) и вставлять их сумму в мультимножество. Процесс следует продолжать до тех пор, пока мультимножество содержит более одного элемента. Если a и b – длины сливаемых последовательностей, то стоимость их слияния равна 2 * (a + b).
#include

#include

using namespace std;
int i, n, a, b, res;

multiset s;
void main(void)

{

scanf("%d",&n);

for(i = 0; i < n; i++)

{

scanf("%d",&a); s.insert(a);

}

res = 0;

while(s.size() > 1)

{

a = *s.begin(); s.erase(s.begin());

b = *s.begin(); s.erase(s.begin());

s.insert(a + b);

res += 2 * (a + b);

}

printf("%d\n",res);

}
^ 6. Планирование производственной линии. Ищем наименьшее значение среди чисел ai и bi (i = 1, n). Если наименьшим значением будет ai, то ставим i - ую деталь первой, если bi – то последней. После этого удаляем i - ую деталь со списка. Повторяем описанный процесс для оставшихся n – 1 деталей.

Реализация. Информация о деталях (ai, bi) хранится в векторе пар v. Детали сортируются при помощи функции сортировки f: деталь (ai, bi) меньше детали (aj, bj), если минимум среди чисел {ai, bi, aj, bj} принадлежит ai или bj.
#include

#include

#include

using namespace std;
int i, n, a, b;

vector
> v;
int f(pair a, pair b)

{

int m[4] = {a.first,a.second,b.first,b.second};

int *min = min_element(m,m+4);

if ((*min == a.first) || (*min == b.second)) return 1;

return 0;

}
void main(void)

{

scanf("%d",&n);

for(i = 0; i < n; i++)

{

scanf("%d %d",&a,&b);

v.push_back(make_pair(a,b));

}

sort(v.begin(),v.end(),f);

for(i = 0; i < v.size(); i++) printf("%d %d\n",v[i].first,v[i].second);

}
^ 7. Игра в игру [Топкодер, раунд 217, дивизион 2, уровень 2]. Отсортируем воинов обоих армий по возрастанию их силы. Следует выставить Вашего самого сильного воина против самого сильного воина оппонента, которого он может одолеть. Потом перейти к следующему по силе воину, найти ему оппонента и так далее.

Рассмотрим первый пример. Отсортируем армии по возрастанию сил воинов:

you = {1, 5, 5, 15, 100}

computer = {1, 5, 5, 15, 100}

Вашего самого сильного воина (с силой 100) следует выставить против компьютерного воина с силой 15 – самого сильного воина оппонента, которого он может победить. Следующего воина с силой 15 следует выставить против 5. Вашего воина с силой 5 выставляем против оппонента с силой 1. Все остальные Ваши воины будут разбиты. Таким образом, после боя сумма сил выживших Ваших воинов будет максимально возможной, и равна 100 + 15 + 5 = 120.
#include

#include

#include

using namespace std;
class PlayGame

{

public:

int saveCreatures(vector you, vector computer)

{

int you_ptr,comp_ptr,res = 0;

sort(you.begin(),you.end());

sort(computer.begin(),computer.end());

you_ptr = comp_ptr = you.size()-1;

while(comp_ptr >= 0)

{

if (you[you_ptr] > computer[comp_ptr])

{

res += you[you_ptr];

you_ptr--;

}

comp_ptr--;

}

return res;

}

};
^ 8. Мост [Вальядолид, 10037]. Отсортируем время, за которое люди пересекают реку, по возрастанию. Обозначим через mi время пересечения реки i – ым человеком (m1m2  …  mn). Рассмотрим, как следует пересекать мост одному, двум или трем людям. При n = 1 и n = 2 оптимальная скорость пересечения реки соответственно равна m1 и m2 = max(m1, m2). При наличии трех людей (n = 3) первый и второй перебираются на другую сторону, самый быстрый (первый) возвращается с фонарем назад и переводит третьего. Таким образом, оптимальное время перехода равно m1 + m2 + m3.

Рассмотрим случай, когда n > 3. Пусть A, B, …, Y, Z – люди, отсортированные по возрастанию времени пересечения моста (A – самый быстрый, Z – самый медленный). Пусть J – это человек, с которым перемещается Z. Если J остается на другом берегу и никогда больше не пойдет по мосту, то оптимально выбрать его равным Y. Если J будет возвращаться, то его оптимально выбрать самым быстрым, то есть А. Таким образом Z может пересекать мост или с Y, или с А. Вычислим время перевода двух самых медленных людей (Y и Z) согласно этим двум стратегиям.

1. Z идет с Y. Но тогда до этого там должен быть кто-то, кто вернет фонарь, например K. Но этого K также на другой берег должен был кто-то провести чтобы, вернув фонарь, отдать его Y и Z. Пусть им будет L. Таким образом, K и L должны возвращаться. Для минимизации времени в качестве K и L следует выбрать двух самых быстрых, то есть A и B. Время перевода Y и Z равно mA + 2mB + mZ.

2. Z идет с A, A возвращается. Аналогично A переводит Y и также возвращается. Время перевода Y и Z равно 2mA + mY + mZ.

В обоих случаях через мост переводятся только двое самых медленных людей. Стратегия (первая или вторая) выбирается в зависимости от того, какое из значений (mA + 2mB + mZ или 2mA + mY + mZ) меньше. Если изначально следовало перевести n людей, то далее рекурсивно следует перевести n – 2 людей.

Пример. Отсортируем время пересечения моста людьми: 1, 2, 5, 10. Здесь mA = 1, mB = 2, mY = 5, mZ = 10. Время перевода двух самых медленных людей согласно первой и второй стратегиям соответственно равны mA + 2mB + mZ = 1 + 2 * 2 + 10 = 15, 2mA + mY + mZ = 2 * 1 + 5 + 10 = 17. Поскольку первое значение меньше, то следует Z вести с Y. Z с Y переводятся за время 15, после чего остается перевести на другой берег A и B. Это делается за время max{mA, mB} = 2.


Реализация. В массиве m хранится время перехода людей через реку. Функция go(n, visible) возвращает оптимальное время, за которое могут пересечь реку n людей. Переменная visible = 1, если следует выводить на экран саму стратегию перехода (visible = 0 иначе).


#include

#include

using namespace std;
int tests,n,i;

int m[1001];
int go(int n,int visible)

{

int First, Second,Best;
Рассматриваем случаи пересечения реки одним, двумя и тремя людьми.
if (n == 1)

{

if (visible) printf("%d\n",m[0]); return m[0];

} else

if (n == 2)

{

if (visible) printf("%d %d\n",m[0],m[1]); return m[1];

} else

if (n == 3)

{

if (visible)

{

printf("%d %d\n",m[0],m[1]);

printf("%d\n",m[0]);

printf("%d %d\n",m[0],m[2]);

}

return m[0] + m[1] + m[2];

};
Вычисляем оптимальное время ^ First и Second, которое получается при использовании двух выше описанных стратегий.
First = m[0] + 2*m[1] + m[n-1];

Second = 2*m[0] + m[n-2] + m[n-1];

Best = (First < Second) ? First : Second;

if (visible)

{

if (Best == First)

{

printf("%d %d\n",m[0],m[1]);

printf("%d\n",m[0]);

printf("%d %d\n",m[n-2],m[n-1]);

printf("%d\n",m[1]);

} else

{

printf("%d %d\n",m[0],m[n-2]);

printf("%d\n",m[0]);

printf("%d %d\n",m[0],m[n-1]);

printf("%d\n",m[0]);

}

}
Рекурсивно вычисляем оптимальную стратегию для оставшихся n – 2 людей.
return Best + go(n-2,visible);

}
void main(void)

{

int res;

scanf("%d",&tests);

while(tests--)

{

scanf("%d",&n);

for(i=0;iСортируем время пересечения реки людьми по возрастанию. Запускаем функцию go с параметром visible = 0, которая возвращает оптимальное время пересечения реки. Выводим его, после чего снова запускаем функцию go с параметром visible = 1, которая печатает последовательность переходов. Если текущий тест не последний, то выводим пустую строку.
sort(m,m+n);

res = go(n,0); printf("%d\n",res);

res = go(n,1);

if (tests) printf("\n");

}

}
^ 9. Все во всем [Вальядолид, 10340]. Читаем первое слово a0a1an-1 в символьный массив line. Второе слово читаем посимвольно. Установим i = 0. Если прочитан символ второго слова, равный ai, то значение i увеличивается на 1. Если после прочтения второго слова i = n, то первое слово является подпоследовательностью второго.

Реализация. Первое слово храним в массиве line. Пока не конец файла, читаем входные тесты. Заносим первое слово в массив line и вычисляем его длину в переменной len. Читаем посимвольно второе слово и изменяем значение переменной i в соответствии с выше описанным алгоритмом. В зависимости от конечного значения переменной i выводим результат.
#include

#include
char line[1000000];
void main(void)

{

int i,len;

char c;

while (!feof(stdin))

{

scanf("%s ",&line);

len = strlen(line); i = 0;

while(scanf("%c",&c),c != '\n') if (c == line[i]) i++;

scanf("\n");

if (i == len) printf("Yes\n"); else printf("No\n");

}

}

СПИСОК ИСПОЛЬЗОВАННЫХ ЗАДАЧ
[Вальядолид] acm.uva.es/problemset:

10037 (Мост), 10340 (Все во всем).
[Топкодер] www.topcoder.com:

SRM 217 (Игра в игру).

Добавить документ в свой блог или на сайт

Похожие:

Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы iconЗадача о медиане 11
Каждый проект состоит из модулей разного типа. Каждый модуль содержит объявления переменных, процедур и функций. Процедуры и функции...

Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы iconМетодические рекомендации по выполнению контрольной работы Контрольная...
Контрольная работа состоит из 10 вариантов, каждый из которых содержит 6 заданий

Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы iconБьерн Страуструп Язык программирования С++ проектирование и развитие
Программа рассматривается как модель реальности, в которой каждый класс представляет определенное понятие. Ключевая задача проектирования...

Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы iconЗадача этой книги состоит в обсуждении исключительно практических...
Задача этой книги состоит в обсуждении исключительно практических вопросов cитуаций и событий, лицом к лицу с которыми трейдер сталкивается...

Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы iconПрограмма на языке С# состоит из последовательности операторов, каждый...
С# состоит из последовательности операторов, каждый из которых определяет законченное описание некоторого действия и заканчивается...

Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы iconРешение о методах выхода на рынок
Каждый последую­щий стратегический подход требует принятия на себя большего объема обязательств и большего риска, но сулит и более...

Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы iconИсследовательская работа по астрономии: «люди и звезды»
Актуальность выбранной мною темы состоит в том, что многие ученики 9 класса теряются при выборе профессии и их всегда интересуют...

Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы iconКонспект урока математики 1 класс Ознакомление с понятием и термином...
Ознакомление с понятием и термином «задача». Составление и решение задач на нахождение суммы и остатка

Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы iconЗадача обеспечения указанных выше требований решается на двух этапах...
Поэтому задача поиска эффективных технологических процессов является задачей технологической оптимизации

Задача решается последовательными локальными выборами, каждый из которых состоит в выборе монеты наибольшего номинала, не большего текущей суммы iconНарод – единственный источник власти
Народ состоит из граждан страны, каждый из которых обладает исключительным правом на управление своей жизнью и имуществом

Вы можете разместить ссылку на наш сайт:
Школьные материалы


При копировании материала укажите ссылку © 2013
контакты
uchebilka.ru
Главная страница


<