![]() |
int pocty[11];Tato definice vytvoří pole s indexy 0 až 10, prvek s indexem 0 zůstane nevyužitý. Druhou možností je vytvoření pole správné velikosti
int pocty[10];v němž jsou ovšem prvky indexovány 0 až 9 a při komunikaci s uživatelem je potřeba vždy tento index zvýšit, příp. snížit o jednu, s čímž souvisí větší riziko zavlečení chyby. Program se tedy na začátku zeptá na počet barev, potom naplní pole počtů kuliček jednotlivých barev a potom provádí cyklus opakující se až do maximálního možného počtu tahů, který přeruší v případě, že je uživatelem zadána barva 0. Výpisy r_02.c a r_02.pas ukazují implementaci tohoto problému.
Funkce(x,y)Stručně si rozeberme, jak bude vypadat výpočet po volání Funkce(4,2): Funkce(4,2) zavolá
Pokud x=0 nebo y=0, vrať 1
Jinak vrať Funkce(x-1,y)+Funkce(x, y-1)
Celkem mě překvapilo, že se někteří z vás ze začátku vrhli na úlohu číslo 1, která rozhodně nebyla nejjednodušší a zaměstnala vás na dost dlouho, takže jste neměli dost času na řešení podstatně jednodušší úlohy číslo 2. To se také projevilo v nízkých bodových ziscích některých z vás
Některým z vás by rozhodně prospělo nejdřív si pořádně všechno rozmyslet a klidně nakreslit nebo napsat na papír, a teprve potom začít programovat. Není nic horšího, než když dopíšete program, a s hrůzou zjistíte, že vůbec neděá to, co jste po něm chtěli. Kdybyste si předem rozmysleli, jak bude váš program při výpočtu postupovat, a nejdřív si tento postup vyzkoušeli na nějakých datech, mohli byste lépe odhalit chyby, které se v návrhu vyskytují a bud provést v návrju patřičné úpravy, nebo se do psaní nefunkčního programu vůbec nepouštět.
Na druhou stranu mě příjemně překvapilo, že se nevyskytli soutěžící, kteří by si ani netukli. I ti, kteří mají nízké bodové zisky, napsali většinou ceé programy, které bohužel ne vždy fungovaly bez chyb -- chyby byly však většinou zaviněny nekvalitním návrhem, jak bylo popsáno v předchozím odstavci, a proto lze věřit, že osvojením lepších postupů při vývoji se vaše programy podstatně zepší.
Mnoho úspěchů při psaní dalších programů vám za ty, kdo se na organizaci tohoto kola podíleli (Jakub Fischer, Pavel Míka, Jan Vodicka) přeje
Jan Vodička
Výpisy programu
Poznámka: za správnost rucím pouze u C-ckovských programu.
Pascal uz si pamatuji jenom mlhave, a proto je mozné, ze v Pascalovských
programech je nejaká syntaktická (ale nikoliv logická) chyba. Omlouvám
se programátorum v Basicu, na ten uz moje síly nestací, a proto dobrá
rada: naucte se Pascal, nebo ješte radeji C.
![]()
#include <stdio.h>
#define OSTROVY 5
int navstiveny[OSTROVY+1];
int spoj[OSTROVY+1][OSTROVY+1];
int ZjistiSpoj(int odkud, int cil)
{
int i;
/* V pripade, ze jsem v cili, vratim 1 */
if (odkud==cil)
return 1;
/* V pripade, ze jsem na tomto ostrove jiz byl, vratim 0 */
if (navstiveny[odkud])
return 0;
/* Jinak ho rovnou oznacim, abych se sem uz nevracel */
navstiveny[odkud]=1;
/* Projdi vsechny ostrovy */
for (i=1;i<=5;i++)
/* Pokud se jedna o jiny ostrov */
if (i!=odkud)
/* Pokud existuje primy spoj */
if (spoj[odkud][i])
/* Pokud z ostrova i lze cestovat do cile */
if (ZjistiSpoj(i,cil))
return 1;
/* Vyzkousel jsem vsechny ostrovy a nikde neuspel, vratim tedy 0 */
return 0;
}
int main(void)
{
int from, to;
int znovu;
int i,j;
/* Prestoze tuto inicializaci vetsina prekladacu provede
automaticky, neni vubec od veci ji tady uvest */
for (i=0;i<=OSTROVY;i++)
navstiveny[i]=0;
for (i=0;i<=OSTROVY;i++)
for (j=0;j<=OSTROVY;j++)
spoj[i][j]=0;
do {
printf("Zadej spoj ve tvaru x-y (0-0=konec):");
do {
znovu=0;
scanf("%i-%i",&from,&to);
if (from<0 || to<0 || from>OSTROVY || to >OSTROVY)
{
printf("Povolene rozmezi je 1 az %i\n",OSTROVY);
znovu=1;
}
spoj[from][to]=1;
} while (znovu);
} while(from != 0 && to != 0);
printf("Zadej hledane spojeni ve tvaru x-y :");
do {
znovu=0;
scanf("%i-%i",&from,&to);
if (from<=0 || to<=0 || from>OSTROVY || to >OSTROVY)
{
printf("Povolene rozmezi je 1 az %i\n",OSTROVY);
znovu=1;
}
} while (znovu);
if (ZjistiSpoj(from,to))
printf("Cesta %i -> %i existuje\n",from,to);
else
printf("Cesta %i -> %i neexistuje\n",from,to);
return 0;
}
Program r_01;
const ostrovy=5;
Var
navstiveny : array[0..5] of boolean;
spoj : array[0..5][0..5] of boolean;
Function ZjistiSpoj(odkud : Integer; cil : Integer) : Integer;
Var
i : Integer;
Begin
{ V pripade, ze jsem v cili, vratim 1 }
If (odkud=cil) Then
Begin
ZjistiSpoj := 1;
Exit;
End { If };
{ V pripade, ze jsem na tomto ostrove jiz byl, vratim 0 }
If (navstiveny[odkud]<>0) Then
Begin
ZjistiSpoj := 0;
Exit;
End { If };
{ Jinak ho rovnou oznacim, abych se sem uz nevracel }
navstiveny[odkud]:=1;
{ Projdi vsechny ostrovy }
for i:=1 to ostrovy do
{ Pokud se jedna o jiny ostrov }
If (i<>odkud) Then
{ Pokud existuje primy spoj }
If (spoj[odkud][i]<>0) Then
{ Pokud z ostrova i lze cestovat do cile }
If (ZjistiSpoj(i, cil)<>0) Then
Begin
ZjistiSpoj := 1;
Exit;
{ Vyzkousel jsem vsechny ostrovy a nikde neuspel,
vratim tedy 0 }
End { If };
ZjistiSpoj := 0;
Exit;
End; { ZjistiSpoj }
Var
from : Integer;
to_1 : Integer;
znovu : boolean;
i : Integer;
j : Integer;
Begin
{ Prestoze tuto inicializaci vetsina prekladacu provede automaticky, }
{ neni vubec od veci ji tady uvest }
for i:=0 to ostrovy do
navstiveny[i]=false;
for i:=0 to ostrovy do
for j:=0 to ostrovy do
spoj[i][j]=false;
Repeat
Write('Zadej spoj ve tvaru x y (0 0=konec):');
Repeat
znovu:=false;
Read(from, to_1);
If (from<0) Or (to_1<0) Or (from>OSTROVY) Or (to_1>OSTROVY) Then
Begin
Writeln('Povolene rozmezi je 1 az ', OSTROVY);
znovu:=true;
End;
spoj[from][to_1]:=true;
Until Not (znovu);
Until Not (((from<>0) And (to_1<>0)));
Write('Zadej hledane spojeni ve tvaru x y :');
Repeat
znovu:=false;
Read(from, to_1);
If (from<=0) Or (to_1<=0) Or (from>OSTROVY) Or (to_1>OSTROVY) Then
Begin
Writeln('Povolene rozmezi je 1 az ', OSTROVY);
znovu:=true;
End;
Until Not (znovu);
If (ZjistiSpoj(from, to_1)<>0) Then
Writeln('Cesta ', from, ' -> ', to_1, ' existuje');
Else
Writeln('Cesta ', from, ' -> ', to_1, ' neexistuje');
End.
#include <stdlib.h>
#define BAREV 10
int pocty[BAREV+1];
int kandidati[BAREV+1];
int main(void)
{
int i,j;
int druhu;
int tahu,spravne;
int tah,tip;
int stejne;
int max;
tahu=0;
spravne=0;
printf("Zadej pocet barev (1 az %i):\n",BAREV);
while(1)
{
scanf("%i",&druhu);
if (druhu<1 || druhu>BAREV)
printf("Povolene rozpeti je 1 az %i)\n",BAREV);
else
/* Pokud je vstup ve spravnem rozpeti, vyskoc z cyklu */
break;
}
/* Inicializace pole poctu */
for (i=1;i<=druhu;i++)
pocty[i]=100;
for (i=0;i<100*druhu;i++)
{
stejne=0;
max=0;
for (j=1;j<=druhu;j++)
{
/* Pokud jsem narazil na dosud nejvyssi pocet, upravim max */
if (max<pocty[j])
{
max=pocty[j];
kandidati[0]=j;
stejne=1;
}
/* Pokud je tento pocet pouze roven maximu, pridam tuto barvu
mezi kandidaty na losovani */
else if (max==pocty[j])
{
kandidati[stejne]=j;
stejne++;
}
}
/* Tento zpusob ziskani nahodneho cisla neni uplne idealni ...
nicmene pro nase ucely plne postacuje */
tip=kandidati[random() % stejne];
printf ("Muj tip: %i\n",tip);
printf ("Cos vytahl?\n");
while(1)
{
scanf("%i",&tah);
if (tah<0 || tah>druhu)
printf("Neplacej nesmysly (mozne rozpeti 1 az %i, 0 \
pro konec)\n",druhu);
else if (pocty[tah]<=0 && tah>0)
printf("Tato barva uz se v sacku nevyskytuje\n");
else
break;
}
if (tah==0)
break;
if (tah==tip)
spravne++;
tahu++;
pocty[tah]--;
}
printf ("Celkovy pocet tahu: %i, z toho spravne uhodnuto: %i\n", \
tahu,spravne);
}
Program r_02;
const barev=10;
Var
pocty : array [1..barev] of integer;
kandidati : array [1..barev] of integer;
i : Integer;
j : Integer;
druhu : Integer;
tahu : Integer;
spravne : Integer;
tah : Integer;
tip : Integer;
stejne : Integer;
max : Integer;
Begin
tahu:=0;
spravne:=0;
Writeln('Zadej pocet barev (1 az ', BAREV, '):');
While (True) Do
Begin
Read(druhu);
If ((druhu<1) Or (druhu>BAREV)) Then
Writeln('Povolene rozpeti je 1 az ', BAREV, ')');
Else
break;
End { While };
{ Inicializace pole poctu }
for i:=1 to druhu do
pocty[i]:=100;
for i:=1 to 100*druhu do
Begin
stejne:=0;
max:=0;
for j:=1 to druhu do
Begin
{ Pokud jsem narazil na dosud nejvyssi pocet, upravim maximum }
If (max<pocty[j]) Then
Begin
max:=pocty[j];
kandidati[0]:=j;
stejne:=1;
End { If }
Else
{ Pokud je tento pocet pouze roven maximu, pridam tuto }
{ barvu mezi kandidaty na losovani }
If (max=pocty[j]) Then
Begin
kandidati[stejne]:=j;
stejne:=Succ(stejne);
End { If };
End { For };
tip:=kandidati[random(stejne)];
Writeln('Muj tip: ', tip);
Writeln('Cos vytahl?');
While (True) Do
Begin
Read(tah);
If ((tah<0) Or (tah>druhu)) Then
Writeln('Neplacej nesmysly (mozne rozpeti 1 az ', druhu, ',
0 pro konec)');
Else
If ((pocty[tah]<=0) And (tah>0)) Then
Writeln('Tato barva uz se v sacku nevyskytuje');
Else
break;
End { While };
If (tah=0) Then
break;
If (tah=tip) Then
spravne:=spravne+1;
tahu:=tahu+1;
pocty[tah]:=pocty[tah]-1;
End { For };
Writeln('Celkovy pocet tahu: ', tahu, ', z toho spravne uhodnuto: ',
spravne);
End.
#define ROZMER 100
int pocet[ROZMER+1][ROZMER+1];
int cest(int m,int n)
{
int i,j;
for (i=0;i<=ROZMER;i++)
{
pocet[0][i]=1;
pocet[i][0]=1;
}
for (i=1;i<=m;i++)
for (j=1;j<=n;j++)
/* Tato mozna ponekud zvlastni podminka je tu kvuli preteceni
... pokud soucet pretece rozmery intu, funkce vrati -1 */
if (pocet[i-1][j]+pocet[i][j-1]>pocet[i-1][j])
pocet[i][j]=pocet[i-1][j]+pocet[i][j-1];
else
return -1;
return pocet[m][n];
}
int main(void)
{
int m,n;
int celkem;
printf("Zadej rozmery site ve tvaru m,n:\n");
while(1)
{
scanf("%i,%i",&m,&n);
if (m<0 || n<0 || m>ROZMER || n>ROZMER)
printf("Mozne rozpeti rozmeru je 0 az %i\n",ROZMER);
else
break;
}
if ((celkem=cest(m,n))==-1)
printf("Bohuzel, pocet cest je prilis veliky\n");
else
printf ("Pocet moznych cest z [0,0] do [%i,%i] je %i.\n",m,n, \
celkem);
}
Program r03;
const rozmer=100;
Var
pocet : array[0..rozmer,0..rozmer] of longint;
Function cest( m : Integer; n : Integer) : Integer;
Var
i : Integer;
j : Integer;
Begin
for i:=0 to rozmer do
Begin
pocet[0,i]:=1;
pocet[i,0]:=1;
End { For };
for i:=1 to m do
for j:=1 to n do
Begin
{ Tato mozna ponekud zvlastni podminka je tu kvuli preteceni }
{ pokud soucet pretece rozmery longintu, funkce vrati -1 }
If (pocet[i-1][j]+pocet[i][j-1]>pocet[i-1][j]) Then
pocet[i][j]:=pocet[i-1][j]+pocet[i][j-1];
Else
Begin
cest := -1;
Exit;
End { Else };
End { For };
End { For };
cest := pocet[m][n];
End; { cest }
Var
m : Integer;
n : Integer;
celkem : longint;
Begin
Writeln('Zadej rozmery site ve tvaru m n:');
While (True) Do
Begin
Read(m, n);
If ((((m<0) Or (n<0)) Or (m>ROZMER)) Or (n>ROZMER)) Then
Writeln('Mozne rozpeti rozmeru je 0 az ', ROZMER);
Else
break;
End { While };
celkem=cest(m,n);
If (celkem=-1) Then
Writeln('Bohuzel, pocet cest je prilis veliky');
Else
Writeln('Pocet moznych cest z [0,0] do [', m, ',', n, '] je ',
celkem, '.');
End.
| Pořadí | Jméno | Body | Celkem | |||||||||||
| 1 | 2 | 3 | 3b | |||||||||||
| 1. | Václav Potoček | 6 | 2,5 | 1 | 6 | 2,5 | 1 | 6 | 3 | 1 | 3 | 1,5 | 0 | 33,5 |
| 2. | Petr Nohavica | 3 | 0 | 1 | 1 | 1 | 1 | 6 | 3 | 1 | 3 | 1,5 | 0 | 21,5 |
| 3. | Tomáš Zvala | 4 | 3 | 1 | 3 | 1,5 | 0 | - | - | - | - | - | - | 12,5 |
| 4.-5. | Pavel Šorejs | 1 | 0 | 0 | 6 | 2 | 1 | - | - | - | - | - | - | 10 |
| 4.-5. | Jan Vater | 3 | 2 | 1 | 3 | 0 | 1 | - | - | - | - | - | - | 10 |
| 6. | Jan Hlavsa | 0 | 0 | 0 | 5 | 3 | 1 | 0,5 | 0 | 0 | - | - | - | 9,5 |
| 7. | Martin Bak | 0,5 | 0 | 0 | 3 | 1,5 | 0,5 | - | - | - | - | - | - | 7,5 |
| 8. | Jakub Vaniš | 0 | 0 | 0 | 3 | 1,5 | 0,5 | - | - | - | - | - | - | 5 |
| 9. | Pavel Pokorný | 1 | 1 | 1 | 0,5 | 0,5 | 0 | 0,5 | 0 | 0 | - | - | - | 4,5 |
| 10.-11. | Dominik Peklo | 0 | 0 | 0 | 3 | 1 | 0 | 0 | 0 | 0 | - | - | - | 4 |
| 10.-11. | Jan Mikolajczyk | 3 | 1 | 0 | - | - | - | - | - | - | - | - | - | 4 |
| 12. | Michal Bernhardt | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,5 | - | - | - | 1,5 |
| 13. | Petr Nohavica | 0 | 1 | 0 | 0 | 0 | 0 | - | - | - | - | - | - | 1 |