1. Затори на дорогах (JAMMINGбалів

Автомобільні затори трапляються усюди, навіть у нашому невеличкому містечку. Дороги у нас мають дві смуги в одному напрямку, а автомобілі є лише двох типів габаритів: легкові (у пробці займають квадрат 1х1, якщо за 1 взяти ширину смуги) та вантажні (у пробці займають місце 2х1 вздовж смуги).

Водії дуже дисципліновані у тому плані, що вони не стають поперек смуги, не займають чужу площу, але й не залишають вільних місць.

Визначте, скільки існує різних за послідовністю типів машин (легкова - вантажна) заторів між мерією міста та моїм будинком, якщо вони на одній вулиці, а відстань між ними S.

Формат вхідних даних:

Вхідний файл містить єдине число S (1£S£10000) – задана відстань.

Формат вихідних даних:

Єдиний рядок вихідного файлу повинен містити відповідь – кількість розстановок автомобілів в першій і другій смузі разом. Достеменно відомо, що кількість цифр у відповіді не перевищує 700.

JAMMING. DAT

JAMMING. SOL

2

4

Приклад вхідних та вихідних даних:

Ідея: Кількість послідовностей для однієї смуги рівне N-1 числу ФІБОНАЧІ, а для двох смуг їх добуток.

const maxl = 1000;

type longint = array [1..maxl] of byte;

procedure add(a, b: longint; var c: longint);

var i, p: integer;

begin

p:=0;

for i:=maxl downto 1 do begin

c[i]:=(a[i]+b[i]+p) mod 10;

p:=(a[i]+b[i]+p) div 10;

end;

end;

procedure mul(a, b: longint; var c: longint);

var i, j, p, t: integer;

begin

fillchar(c, sizeof(c), 0);

for i:=maxl downto 1 do begin

НЕ нашли? Не то? Что вы ищете?

p:=0;

for j:=maxl downto 1 do begin

t:=c[i+j-maxl] + a[i]*b[j] + p;

c[i+j-maxl]:=t mod 10;

p:=t div 10;

end;

end;

end;

var f0, f1, f2: longint;

i, n: integer;

begin

assign(input, 'jamming. dat'); reset(input );

assign(output, 'jamming. sol'); rewrite(output);

readln(n);

fillchar(f0, sizeof(f0), 0);

fillchar(f1, sizeof(f1), 0); f1[maxl]:=1;

for n:=1 to n do begin

add(f0, f1, f2);

f0:=f1; f1:=f2;

end;

mul(f1, f1, f1);

i:=1; while f1[i]=0 do inc(i);

for i:=i to maxl do write(f1[i]); writeln;

close(input); close(output);

end.

TEST0

2

4

TEST1

3

9

TEST2

5

64

TEST3

10

7921

TEST4

12

54289

TEST5

15

974169

TEST6

17

6677056

TEST7

20

119814916

TEST8

406

26119758617711589056112697415390198449842420677629708065941562510465159210226699689676276740874458452907821742441231594373811457250753819075046821231149755254052955180769

TEST9

1010

74823596808418144970832931075942523313227960460987707983746990533162495270593096468852414371653558710956498765971157709676253706234052411287783327917220645748754354985882428209769136507030647457402031371855271988911864004344052461849484499317176804346208410597013046033628808875330074698301533647372254009620738815298130640699378693817405983105033855835318787824438605173037801038556184408842470090070596513692249434081796

3 -- 2

4 -- 3

5 -- 5

6 -- 8

7 -- 13

8 -- 21

9 -- 34

10 -- 55

11 -- 89

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

5


2. Найкоротший шлях (PATH)

На площині задано прямокутників зі сторонами, паралельними осям координат, та дві різні точки та . Ніякі два прямокутники не перетинаються і не дотикаються одне одного. Точки та не належать жодному з прямокутників. Шлях між точками та може дотикатися вершин і проходити вздовж сторін прямокутників, але не повинен заходити всередину прямокутників. Визначте довжину найкоротшого шляху між точками та .

Формат введення/виведення:

Напишіть програму PATH, яка читає координати точок та прямокутників з файлу PATH. DAT і записує довжину найкоротшого шляху у файл PATH. SOL.

У першому рядку файлу PATH. DAT знаходиться число . У другому рядку знаходяться координати та точки . У третьому рядку знаходяться координати та точки . У наступних рядках знаходиться по чотири числа – координати протилежних вершин -го прямокутника.

Шукана довжина повинна бути визначена із точністю до (це значить, що ваша відповідь не повинна відрізнятися від відповіді журі більш, ніж на ).

Обмеження: .

Приклад:

PATH. DAT:

2

2

1

PATH. SOL:

20.093368739633874

Розв’язок задачі:

Дана задача є нестандартною інтерпретацією стандартних алгоритмів пошуку найкоротших шляхів на графі. Одразу ж можна сказати, що шуканий шлях проходитиме лише через точки А та B і вершини прямокутників (можливо, уздовж їх сторін). Тому закономірно, зводячи задачу до графа, вважати вершинами останнього вершини прямокутників, а ребрами – можливість пролягання шляху по відрізку, що сполучає пару таких вершин.

Для можливості роботи з нашим графом необхідно для кожної пари вершин визначити, чи існує між ними ребро. Тобто, чи не перетинає якийсь із прямокутників відрізок, що їх сполучає.

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

Можна користуватися такою умовою: відрізок AB перетинає відрізок CD тоді і тільки тоді, коли точки A та B знаходяться по різні боки від прямої CD і навпаки, точки C та D знаходяться по різні боки від прямої AB.

function line2line(x11,y11,x12,y12,

x21,y21,x22,y22:real):boolean;

function cmp(x, y,x1,y1,x2,y2:real):real;

var a, b,c:real;

begin

a:=y1-y2;

b:=x2-x1;

c:=x1*y2-x2*y1;

cmp:=a*x+b*y+c;

end;

begin

line2line:=(cmp(x11,y11,x21,y21,x22,y22)*

cmp(x12,y12,x21,y21,x22,y22) <0) and

(cmp(x21,y21,x11,y11,x12,y12)*

cmp(x22,y22,x11,y11,x12,y12) <0);

end;

На базі цієї підпрограми можна написати ще одну, яка визначатиме, чи перетинаються прямокутник та відрізок.

function line2rect(x1,y1,x2,y2,rx1,ry1,rx2,ry2:real):boolean;

begin

line2rect:=line2line(x1,y1,x2,y2,rx1,ry1,rx1,ry2)

or line2line(x1,y1,x2,y2,rx1,ry2,rx2,ry2)

or line2line(x1,y1,x2,y2,rx2,ry2,rx2,ry1)

or line2line(x1,y1,x2,y2,rx2,ry1,rx1,ry1);

end;

Слід звернути увагу на те, що у даній задачі ми маємо справу зі зваженим графом. Якщо ребро між двома вершинами існує, то припишемо йому вагу, рівну його довжині.

Тепер, коли граф побудовано, можна реалізувати на ньому алгоритм Дейкстри для знаходження найкоротшого шляху між точками A та B.

const maxn = 30;

infinity = 1e20;

function cmp(x, y,x1,y1,x2,y2:real):real;

var a, b,c:real;

begin

a:=y1-y2;

b:=x2-x1;

c:=x1*y2-x2*y1;

cmp:=a*x+b*y+c;

end;

function line2line(x11,y11,x12,y12,

x21,y21,x22,y22:real):boolean;

begin

line2line:=(cmp(x11,y11,x21,y21,x22,y22)*

cmp(x12,y12,x21,y21,x22,y22)<0) and

(cmp(x21,y21,x11,y11,x12,y12)*

cmp(x22,y22,x11,y11,x12,y12)<0);

end;

function line2rect(x1,y1,x2,y2,rx1,ry1,rx2,ry2:real):boolean;

begin

line2rect:=line2line(x1,y1,x2,y2,rx1,ry1,rx1,ry2)

or line2line(x1,y1,x2,y2,rx1,ry2,rx2,ry2)

or line2line(x1,y1,x2,y2,rx2,ry2,rx2,ry1)

or line2line(x1,y1,x2,y2,rx2,ry1,rx1,ry1);

end;

function len(x1,y1,x2,y2:real):real;

begin

len:=sqrt(sqr(x1-x2)+sqr(y1-y2));

end;

var i, j,k, n,qh, qt:integer;

r:array [0..maxn*4+1,1..2] of real;

g:array [0..maxn*4+1,0..maxn*4+1] of boolean;

Q:array [1..maxn*maxn] of byte;

s:array [0..maxn*4+1] of real;

begin

assign(input,'path. dat'); reset(input);

assign(output,'path. sol'); rewrite(output);

readln(n, r[0,1],r[0,2],r[n*4+1,1],r[n*4+1,2]);

for i:=1 to n do begin

readln(r[i,1],r[i,2],r[i+2*n,1],r[i+2*n,2]);

r[i+n,1]:=r[i,1]; r[i+n,2]:=r[i+2*n,2];

r[i+3*n,1]:=r[i+2*n,1]; r[i+3*n,2]:=r[i,2];

end;

for i:=0 to 4*n do

for j:=i+1 to 4*n+1 do

if (i=0)or(j=4*n+1)or(i+2*n<>j) then begin

g[i, j]:=true;

for k:=1 to n do

if line2rect(r[i,1],r[i,2],

r[j,1],r[j,2],

r[k,1],r[k,2],

r[k+2*n,1],r[k+2*n,2]) then

begin

g[i, j]:=false;

break;

end;

g[j, i]:=g[i, j];

end;

for i:=1 to maxn*4+1 do s[i]:=infinity;

Q[1]:=0; qh:=1; qt:=1;

while qh<=qt do begin

for i:=1 to maxn*4+1 do

if g[Q[qh],i] and

(len(r[Q[qh],1],r[Q[qh],2],

r[i,1],r[i,2])+s[Q[qh]]<s[i]) then

begin

inc(qt);

Q[qt]:=i;

s[i]:=len(r[Q[qh],1],r[Q[qh],2],

r[i,1],r[i,2])+s[Q[qh]];

end;

inc(qh);

end;

writeln(s[4*n+1]:0:6);

close(input); close(output);

end.

TEST0

2

2

1

20.093369

TEST1

1

0 0

0 3

102.225300

TEST2

1

5.000000

TEST3

1

12.000000

TEST4

1

12.000000

TEST5

2

12.000000

TEST6

3

0

12.211450

TEST7

5

0 0

11 11

15.556349

TEST8

5

0 0

11 11

16.119695

TEST8

10

1 0

2

11

13

15

17

1

102.225300