Обещах повече да не пиша във форума и това наистина е последният ми пост просто заради задачата на демонд.
CODE
char goal_state ( char MSgrid[ROWS][COLS] )
{
char goal_state=’Y’;
int blankcount=0;
for (int i=0; i<ROWS; i++)
for (int j=0; j<COLS; j++)
if (MSgrid[i][j]==’?’)
blankcount++;
if (blankcount > 0)
goal state=’N’;
else
{
int bombs_expected=0;
int bombs=0;
int i, j;
for ( i=0; i<ROWS && goal_state==’Y’; i++ )
{
for ( j=0; j<COLS && goal_state==’Y’; j++ )
{
bombs_expected=char_to_int( MSgrid[i][j] );
if ( bombs_expected != 9 )
{
bombs=surrounding_bombs( MSgrid, i, j );
if ( bombs_expected != bombs )
goal_state=’N’;
}
}
}
}
return goal_state;
}
int surrounding_bombs ( char MSgrid[ROWS][COLS], int row, int col )
{
int bombcount=0;
if ( row==0 || col==0 || row==(ROWS-1) || col==(COLS-1) )
{
if ( row==0 && col==0 )
{
if ( MSgrid[0][1]==’B’)
bombcount++;
if ( MSgrid[1][0]==’B’)
bombcount++;
if ( MSgrid[1][1]==’B’)
bombcount++;
}
if ( row==0 && col==(COLS-1) )
{
if ( MSgrid[0][col-1]==’B’ )
bombcount++;
if ( MSgrid[1][col]==’B’)
bombcount++;
if ( MSgrid[1][col-1]==’B’ )
bombcount++;
}
if ( row==(ROWS-1) && col==0 )
{
if ( MSgrid[row-1][0]==’B’ )
bombcount++;
if ( MSgrid[row-1][1]==’B’ )
bombcount++;
if ( MSgrid[row][1]==’B’ )
bombcount++;
}
if ( row==(ROWS-1) && col==(COLS-1) )
{
if ( MSgrid[row-1][col-1]==’B’ )
bombcount++;
if ( MSgrid[row-1][col]==’B’ )
bombcount++;
if ( MSgrid[row][col-1]==’B’ )
bombcount++;
}
if ( (row==0) && (col!=0) && (col!=(COLS-1)) )
{
for (int i=0; i<2; i++)
for (int j=(col-1); j<=(col+1); j++)
if (MSgrid[i][j]==’B’)
bombcount++;
}
if ( (row==(ROWS-1)) && (col!=0) && (col!=(COLS-1)) )
{
for (int i=(row-1); i<=row; i++)
for (int j=(col-1); j<=(col+1); j++)
if (MSgrid[i][j]==’B’)
bombcount++;
}
if ( (col==0) && (row!=0) && (row!=(ROWS-1)) )
{
for (int i=(row-1); i<=(row+1); i++)
for (int j=0; j<2; j++)
if (MSgrid[i][j]==’B’)
bombcount++;
}
if ( (col==(COLS-1)) && (row!=0) && (row!=(ROWS-1)) )
{
for (int i=(row-1); i<=(row+1); i++)
for (int j=(col-1); j<=col; j++)
if (MSgrid[i][j]==’B’)
bombcount++;
}
}
else
{
for ( int i=(row-1); i<=(row+1); i++)
{
for ( int j=(col-1); j<=(col+1); j++)
{
if ( MSgrid[i][j] == ’B’ )
bombcount++;
}
}
}
return bombcount;
}
Това са двете функций които решават задачата, всъщност в задачата не е казано че има "unknown" полета(отбелязани с "?"), така, че първата функция може да бъде:
CODE
char goal_state ( char MSgrid[ROWS][COLS] )
{
char goal_state=’Y’;
int blankcount=0;
for (int i=0; i<ROWS; i++)
for (int j=0; j<COLS; j++)
{
int bombs_expected=0;
int bombs=0;
int i, j;
for ( i=0; i<ROWS && goal_state==’Y’; i++ )
{
for ( j=0; j<COLS && goal_state==’Y’; j++ )
{
bombs_expected=char_to_int( MSgrid[i][j] );
if ( bombs_expected != 9 )
{
bombs=surrounding_bombs( MSgrid, i, j );
if ( bombs_expected != bombs )
goal_state=’N’;
}
}
}
}
return goal_state;
}
Moje bi trqbva malko da se obosnova, za tezi na koito ne im e qsno, i pak da ne zemat da me besqt zaradi google.. ta ideqta e slednata:
- minnoto pole se zadava kato dvumeren masiv s razmer [ROWS][COLS]
-funkciata goal_state() obikalja vsjako kvadratche ot poleto zapochvajki ot [0][0]
-za vsjako kvadratche proverjava kakvo chislo e zapisano v nego ( vjako chislo pokazva broja na "bombite" koito obgrajdat tekushtoto kvadratche) i vika funkcijata "surrounding_bombs()"
-"surrounding_bombs()" obikalja kvadratchetata koito obgrajdat tekushtoto kvadratche (za koeto se pravi proverkata) i vryshta broja na bombite koito go obgrajdat
-vav funkciata goal_state() se proverjava dali broja na bombite zapisani v tekushtoto kvadratche ("bombs_expected") e raven na broja na bombite koito go obgrajdat (t.e. stojnostta na chisloto vyrnato ot "surrounding_bombs()")
-ako bombs_expected == surrounding_bombs() za vsichki kvadratcheta (t.e. za vseki element na masiva MSgrid[ROWS][COLS] znachi taka zadadenite vhodni danni (minno pole) sa verni.
bombite sa otbeljazani s "B"
Tova e obshto vzeto.
demond DA RAZBRAH VECHE KAKVO IMASH V PREDVID SHTE POPRAVQ NESHTATA I SHTE GI SLAGAM V TOZI POST TYI KATO TOVA E POSLEDNIQT MI POST. NO MALKO PO KUSNO SHE Q SLOJA ZA DA Q POPRAVQ....
CODE
dobavja se edna nova funkcia, kojato namira dali konkretnoto reshenie e "consistentno", t.e. dali izobshto ima reshenie
char consistency ( char MSgrid[ROWS][COLS] )
{
int bombs_expected=0;
int bombs=0;
int qs=0;
int bombs_qs=0;
char consistency=’Y’;
int i,j;
for (i=0; i<ROWS && consistency!=’N’; i++)
for (j=0; j<COLS && consistency!=’N’; j++)
{
bombs_expected=char_to_int( MSgrid[i][j] );
if ( bombs_expected!=9 )
{
bombs=surrounding_bombs( MSgrid, i, j );
qs=surrounding_unknowns( MSgrid, i, j );
bombs_qs=bombs+qs;
if ( (bombs>bombs_expected) || (bombs_qs<bombs_expected) )
consistency=’N’;
}
}
return consistency;
}
kakto i edna funkcija kojato namira "unknown" poletata zaobikaljashti dadenoto kvadratche
CODE
int surrounding_unknowns ( char MSgrid[ROWS][COLS], int row, int col )
{
int unknowns=0;
if ( row==0 || col==0 || row==(ROWS-1) || col==(COLS-1) )
{
if ( row==0 && col==0 )
{
if ( MSgrid[0][1]==’?’)
unknowns++;
if ( MSgrid[1][0]==’?’)
unknowns++;
if ( MSgrid[1][1]==’?’)
unknowns++;
}
if ( row==0 && col==(COLS-1) )
{
if ( MSgrid[0][col-1]==’?’ )
unknowns++;
if ( MSgrid[1][col]==’?’)
unknowns++;
if ( MSgrid[1][col-1]==’?’ )
unknowns++;
}
if ( row==(ROWS-1) && col==0 )
{
if ( MSgrid[row-1][0]==’?’ )
unknowns++;
if ( MSgrid[row-1][1]==’?’ )
unknowns++;
if ( MSgrid[row][1]==’?’ )
unknowns++;
}
if ( row==(ROWS-1) && col==(COLS-1) )
{
if ( MSgrid[row-1][col-1]==’?’ )
unknowns++;
if ( MSgrid[row-1][col]==’?’ )
unknowns++;
if ( MSgrid[row][col-1]==’?’ )
unknowns++;
}
if ( (row==0) && (col!=0) && (col!=(COLS-1)) )
{
for (int i=0; i<2; i++)
for (int j=(col-1); j<=(col+1); j++)
if (MSgrid[i][j]==’?’)
unknowns++;
}
if ( (row==(ROWS-1)) && (col!=0) && (col!=(COLS-1)) )
{
for (int i=(row-1); i<=row; i++)
for (int j=(col-1); j<=(col+1); j++)
if (MSgrid[i][j]==’?’)
unknowns++;
}
if ( (col==0) && (row!=0) && (row!=(ROWS-1)) )
{
for (int i=(row-1); i<=(row+1); i++)
for (int j=0; j<2; j++)
if (MSgrid[i][j]==’?’)
unknowns++;
}
if ( (col==(COLS-1)) && (row!=0) && (row!=(ROWS-1)) )
{
for (int i=(row-1); i<=(row+1); i++)
for (int j=(col-1); j<=col; j++)
if (MSgrid[i][j]==’?’)
unknowns++;
}
}
else
{
for ( int i=(row-1); i<=(row+1); i++)
{
for ( int j=(col-1); j<=(col+1); j++)
{
if ( MSgrid[i][j] == ’?’ )
unknowns++;
}
}
}
return unknowns;
}
tova e matrica (dvumeren masiv) s razmeri [ROWS][COLS], kakto se zabelqzva
stojnostta na vseki element ot masiva e ili bomba, ili chislo, ili "neizvestno"
algoritama e sys slojnost 0(2^n), kadeto n=ROWSxCOLS
vav funkciata gal_state se dobavja syshto:
CODE
char goal_state ( char MSgrid[ROWS][COLS] )
{
char goal_state=’Y’;
int blankcount=0;
for (int i=0; i<ROWS; i++)
for (int j=0; j<COLS; j++)
if (MSgrid[i][j]==’?’)
blankcount++;
if (blankcount > 0)
goal_state=’N’;
else
{
ova parche kod vzema pod vnimanie "praznite" poleta
GRESHKA GRESHKA
obache sega kato cheta - zadachata ZA 10 TI PAT e malko po razlichna:
dadena e reshetkata s chisla i zakriti poleta
tyrsi se vazmojnite razpolojenia na bombite v zakritite poleta, taka che da udovoletvorjavat reshetkata i da ne nadvishavat predvaritelno zadadenija broj bombi
hm ........"consistentnostta" pokazva che dadenia grid ima reshenie pri taka zadadenite chisla v reshetkata
"goal_state" pokazva che dadenoto konkretno reshenie (t.e. s veche opredeleni mesta na "bombite") e vjarno,
taka che:
QUOTE
kакто недвусмислено е казано в условието - е да се провери дали има разположение на известен брой мини в зададена конфигурация от открити и ЗАКРИТИ полета което удовлетворява цифрите в откритите полета - т.е. мините не са маркирани
se reshava tochno ot funkciata "consitency()"
samo trjabva kato parametar da se vkluchi broja na minite, kojto e zadaden predvaritelno
sajalqvam che pisha taka no se nalaga.....
QUOTE
задачата е да се провери дали тия цифри са валидни
da de, ama trjabva da znaesh kolko broja mini imash predvaritelno
i da proverish dali toja broj mini moje da se razpoloji v igralnoto pole, taka che da udovoletvori dadenite cifri: primerno znaesh che trjabva da tyrsish 20 mini i tolkova.
Ta znachi algoritama kojto se seshtam i moje da reshi tova e "back-trecking"
imame dadena matrica kato na snimkata
zapochvame ot kvadratche [0][0]
ako e markitano s '?' (t.e. e zakrito i njama chislo v nego) - postavjame bomba (zapisvame v nego 'B')
minavame kym sledvashtoto kvadratche
i taka dokato broja na bombite koito sme postavili dostigne predvaritelno zadadenija
vtora chast:
proverjavame s goal_state() dali reshenieto e vjarno
ako ne e se vryshtame nazad - t.e. premestvame poslednoto kvadratche, i taka dokato izcherpim vsichki kombinacii s nego
ako ne stane - vryshtame se na predposlednoto kvadratche i probvame s premestvane na nego
i t.n.
Trqbva mi malko vreme za da napisha gorespomenatiq algoritym....na 70% sym gotova...
Mislq che e tova:
CODE
void add_bomb(char MSgrid[ROWS][COLS], int row, int col, int bomb_total, int bomb_count)
{
if(MSgrid[ROWS][COLS]=='?')
MSgrid[ROWS][COLS] = 'B'
bomb_count++;
if(bomb_count == bomb_total)
if(goal_state == 'Y')
print_array(MSgrid[ROWS][COLS]); //imame reshenie i go razpechatvame
else
return
else
{
if(col == COLS && row < ROWS)
return
else
{
add_bomb(MSgrid[ROWS][COLS], row, col+1, bomb_total, bomb_count);
add_bomb(MSgrid[ROWS][COLS], row+1, 0, bomb_total, bomb_count);
}
}
}
moje i da ima malka logicheska greshka njakade - rekursia ne sam pisala ot mnogo otdavna.
Доказано е, че всяка задача, която може да се реши рекурсивно, може да се реши итеративно (без рекурсия) и обратно. Има обаче такива задачи, които се решават много лесно с рекурсия, а иначе създават доста проблеми. Такава е задачата за търсене на път в лабиринт. Поставете се в ролята на човече, което обикаля в огромен лабиринт и търси изхода. Да приемем, че единственото оръжие, с което разполага човечето е силна памет или просто парче тебешир, с което да си отбелязва пътя. Тази задача наистина се решава трудно без рекурсия, но с рекурсия решението е доста лесно. Всъщност този алгоритъм съвсем несъзнателно се прилага от всеки човек, който се е загубил. Идеята за рекурсивно решение е следната:
CODE
търси_изход(X,Y) {
Дъно на рекурсията: {
Ако сме били тук,
връщаме се, няма смисъл да се въртим в кръг.
Ако сме стигнали до изхода, т.е. точката (X,Y) е изходът,
край, спасени сме
Ако сме стигнали до задъдена улица,
връщаме се обратно.
}
Стъпка на рекурсията: Пробваме {
търси_изход(X-1,Y);
търси_изход(X+1,Y);
търси_изход(X,Y+1);
търси_изход(X,Y-1);
}
}
Така сведохме задачата за търсене на изхода до 4 подзадачи - търсене на изход наляво, търсене на изход надясно, търсене на изход нагоре и търсене на изход надолу. Същевременно знаем как да определим дали най-простата задача е решена - ако сме намерили изхода, или че не е решена - ако сме се “задънили”. Същевременно проверяваме да не би да се въртим в кръг. Този подход се нарича “търсене с връщане назад” (backtracking).
Ta klasicheskoto prilojenie na "backtracking" algorityma e pri reshavane na zadachata "tyrsene na pyt v labirint" a syshto i na "Hanojskite kuli"
v sluchaja az pravja neshto podobno - opitvam se da slagam posledovatelno mini edna sled druga i kato dostigna neobhodimija broj - proverjavam dali imame reshenie na zadachata ("goal_state")
ako njamame reshenie - vryshtam nazad kato premestvam poslednata slojena mina
kato izcherpam vsichki vazmojnosti - maham poslednata i premestvam predposlednata, slagam sled tova pak poslednata mina - i proverjavam
i taka dokato poluchim (ili ne) reshenie.
Ami tova e umstvenite mi sposobnosti sa tolkova sajalqvam no nemoga da izmislq nishto drugo kato gledam tova si e nqkakav matematicheski problem i horata disertacii pishat za nego...
Ami tova e naistina az bqh do tuk poveche nishto nemoga da izmislq jelaq na vsichki vsichko nai hubavo i uspeh sys zadachata...