Guest User

Untitled

a guest
Apr 20th, 2018
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.77 KB | None | 0 0
  1. /********************************************************
  2. *
  3. * KISS GERGO <neptun>
  4. *
  5. * Hány € volt a számla összege annak a gyereknek az esetében,
  6. * akinek lakcíme a leginkább északra esik azok közül a gyerekek közül,
  7. * akiket arról a bázisról szolgáltak ki,
  8. * amelyik mind közül a legdélebbre fekszik?
  9. *
  10. **********************************************************/
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. //#include <math.h>
  15.  
  16.  
  17. double sqrt( double d )
  18. {
  19. double min = 1.0, max = d;
  20. double mid;
  21. double midsquare;
  22. double EPS = 1E-5;
  23. while (max-min > EPS) {
  24. mid = (max+min)/2.0;
  25. midsquare = mid*mid;
  26. if (midsquare < d) {
  27. min = mid;
  28. } else {
  29. max = mid;
  30. }
  31. }
  32.  
  33. return mid;
  34. }
  35.  
  36.  
  37.  
  38. // egyirányú láncolt lista a bázisok tárolására
  39. // tárolja: x és y koordináta
  40. struct base_list {
  41. int x,y;
  42. struct base_list* next;
  43. };
  44. typedef struct base_list Base;
  45.  
  46. // kétirányú lista a legdélebbi bázishoz tartozó gyerekek tárolásához
  47. typedef struct child_list{
  48. int x,y; // koordináták
  49. int gift_num, cash; // kért ajándékok száma; szülõ által befizetett pénz
  50. char gift[26]; // kért ajándékok betûjelei
  51. struct child_list* next; // következõ listaelem
  52. struct child_list* prev; // elõzõ listaelem
  53. double distance; // a kiszolgálás során az elõzõ megállótól való távolság
  54. } Child;
  55.  
  56.  
  57. /**********************************************************************
  58. * a bázisok beolvasása a BASE.DAT fájlból
  59. * visszatérünk a lista kezdõcímével
  60. ***********************************************************************/
  61. Base* ReadBases(){
  62.  
  63. FILE* f;
  64. int temp[2]; // átmeneti tároló a beolvasott koordinátapárnak
  65. Base* base_act; // ciklusváltozó
  66. Base* base_begin; // lista eleje
  67.  
  68. // fájl megnyitása, nincs hibakezelés
  69. f = fopen("BASE.DAT", "r");
  70.  
  71. // strázsának lefoglalunk egy listaelemet
  72. base_act = base_begin = (Base*)malloc(sizeof(Base));
  73. // ciklus amíg a fájl végére nem érünk,
  74. // minden ciklusban beolvasunk egy koordinátapárt majd létrehozzuk a megfelelõ listaelemet
  75. while( fread(temp, sizeof(int), 2, f) ){
  76. base_act->next = (Base*)malloc(sizeof(Base));
  77. base_act = base_act->next;
  78. // tempbe lett beolvasva x és y
  79. base_act->y = temp[0];
  80. base_act->x = temp[1];
  81. }
  82. // a lista végére is strázsát rakunk, melynek next pointere NULL
  83. base_act->next = (Base*)malloc(sizeof(Base));
  84. base_act = base_act->next;
  85. base_act->next = NULL;
  86.  
  87. // fálj bezárása
  88. fclose(f);
  89.  
  90. // visszatérés a bázisok listájának elejével
  91. return base_begin;
  92. }
  93.  
  94.  
  95. /*****************************************************************
  96. * legdélebbi bázis megkeresése
  97. *****************************************************************/
  98. Base* findSouthestBase(Base* base_begin){
  99. Base* min = base_begin->next; // elsõ elem a listából
  100. Base* act; // ciklusváltozó
  101.  
  102. // szokásos minimumkeresési algorutmus
  103. for (act = base_begin->next; act->next != NULL; act = act->next){
  104. if (act->y < min->y){
  105. min = act;
  106. }
  107. }
  108.  
  109. // visszatérés a legdélebbi bázis mutatójával
  110. return min;
  111. }
  112.  
  113.  
  114. /**********************************************************************************
  115. * legészakabbi olyan gyerekek megkeresése, akit a legdélebbi bázisról szolgálnak ki.
  116. * visszatér a feltételnek megfelelõ gyerekek láncolt listájának elejével
  117. * paraméterként a bázisok listáját és a legdélebbi bázist várja
  118. ***********************************************************************************/
  119. Child* searchChildrenSouth(Base* baseBegin, Base* southestBase){
  120. FILE* f;
  121. int x, y, cash, i;
  122. Base* act = baseBegin; // ciklusváltozó
  123. Base* nearBase = NULL; // egy gyerekhez legközelebb esõ bázis
  124. double minDist; // bázisoktól való legkisebb távolság tárolására
  125. Child* child_begin; // gyerekek listájának eleje
  126. Child* j; // ciklusváltozó
  127. Child* child_act; // ciklusváltozó
  128. char temp[60]; // ajándékok ideiglenes tárolója
  129.  
  130. //fájl megnyitása
  131. f = fopen("GIFT.TXT", "rt");
  132.  
  133. // lista elejére létrehozzunk egy strázsa elemet.
  134. child_begin = child_act = (Child*)malloc(sizeof(Child));
  135. // amíg a fájl végére nem érünk egy egy gyerek adatait dolgozzuk fel.
  136. // a feldolgozás csak akkor történik meg ha az a legdélebbi bázishoz tartozik
  137. // egyébként az adataival nem foglalkozunk
  138. // a ciklus fejlécében egy gyerek koordinátáit olvassuk be
  139. while ( fscanf(f, "%d %d\n", &y, &x) != EOF ){
  140.  
  141. minDist = 999999999.9; // kezdeti távolság
  142. // végig megyünk a bázisokon és kikeressül a gyerekhez legközelebb fekvõt
  143. for (act = baseBegin->next; act->next != NULL; act = act->next){
  144. // pitagórasz tétel alapján ha a távolság kisebb mint az eddig talált minimum
  145. // akkor ezt tekintjük a legközelebbi bázisnak
  146. if ( sqrt( (act->x-x)*(act->x-x) + (act->y-y)*(act->y-y)) < minDist ){
  147. minDist = sqrt((act->x-x)*(act->x-x) + (act->y-y)*(act->y-y));
  148. nearBase = act;
  149. }
  150. }
  151.  
  152. // ha a legközelebbi bázis megegyezik a legdélebbivel akkor feldolgozzuk a gyerek adatait
  153. if (nearBase == southestBase){
  154. // listaelem létrehozása és feltöltése
  155. child_act->next = (Child*) malloc(sizeof(Child));
  156. child_act = child_act->next;
  157. child_act->x = x;
  158. child_act->y = y;
  159. child_act->gift_num = 0;
  160. // az ajándékok beolvasása egy ideiglenes tömbbe
  161. fgets(temp,60,f);
  162. // ebbõl kidobjuk a szóközöket
  163. for(i=0; temp[i]!='\0'; i++){
  164. if (temp[i] != ' ' && temp[i] != '\n'){
  165. child_act->gift[child_act->gift_num++] = temp[i];
  166. }
  167. }
  168. // a biztosnág kedvéért lezérjuk nullával
  169. child_act->gift[child_act->gift_num] = '\0';
  170. // az szülõk álltal adott összeg beolvasása
  171. fscanf(f, "%d\n",&cash);
  172. child_act->cash = cash;
  173. }
  174. else{
  175. // ha nem a legdélebbihez tartozik a gyerek akkor 2 sort beolvasunk de nem csinálunk velük semmit
  176. fgets(temp, 60, f);
  177. fgets(temp, 60, f);
  178. }
  179. } // while ciklus vége
  180.  
  181. // lezéró strázsa létrehozása
  182. child_act->next = (Child*)malloc(sizeof(Child));
  183. child_act = child_act->next;
  184. child_act->next = NULL;
  185.  
  186. //fájl lezárása
  187. fclose(f);
  188.  
  189. // kétirányúsításhoz a visszafele mutató pointerek beállítása
  190. child_begin->prev = NULL;
  191. for (j = child_begin; j->next != NULL; j = j->next){
  192. j->next->prev = j;
  193. }
  194.  
  195. // visszatérés a gyerekek listájával
  196. return child_begin;
  197. }
  198.  
  199.  
  200. /************************************************************************
  201. * A gyerekek listáját rendezi a kiszállítási sorrendnek megfelelõen
  202. * paraméterül a gyerekek listáját és az induló bázist várja
  203. * a rendezés közben kiszámolja a kiszállítás során azt a távolságot amit az elõzõ megállótól megtettek
  204. **************************************************************************/
  205. void calcDistAndSort(Child* childBegin, Base* baseFrom){
  206. Child* i; // ciklusváltozó
  207. Child* j; // ciklusváltozó
  208. Child* minChild; // adott ponthoz legközelebbi gyerek
  209. double min; // legközelebbi gyerek távolsága adott ponttól
  210.  
  211. // a strázsát felhasználjuk arra hogy a bázis koordinátáit tárolja
  212. // így lényegesen leegyszerûsödik a bejárási útvonal megtalálása
  213. childBegin->x = baseFrom->x;
  214. childBegin->y = baseFrom->y;
  215.  
  216. // felállítjuk a távolság szerinti sorrendet
  217. for (i = childBegin; i->next->next != NULL; i = i->next){
  218. min = 9999999.9;
  219. // megkeressük az aktuálisan vizsgált megállóhoz (kezdetben a bázis) legközelebbi gyereket
  220. for (j = i->next; j->next != NULL; j = j->next){
  221. if ( sqrt((i->x - j->x)*(i->x - j->x) + (i->y - j->y)*(i->y - j->y)) < min ){
  222. min = sqrt((i->x - j->x)*(i->x - j->x) + (i->y - j->y)*(i->y - j->y));
  223. minChild = j;
  224. }
  225. }
  226. // a megtalált legközelebbi gyereket az adott pont mögé helyezzük át a listában
  227. minChild->prev->next = minChild->next;
  228. minChild->next->prev = minChild->prev;
  229. minChild->next = i->next;
  230. minChild->prev = i;
  231. minChild->next->prev = minChild;
  232. i->next = minChild;
  233. // távolság eltárolása
  234. minChild->distance = min;
  235. }
  236. }
  237.  
  238.  
  239. /**********************************************************************
  240. * A feladat kérdésére (lásd fent) a választ ez a függvény számolja ki
  241. * paraméterül a gyerekek listáját várja
  242. * visszatérni meg a számla összegével fog
  243. **********************************************************************/
  244. int calcNorthestChildPrice(Child* childBegin){
  245.  
  246. FILE* f;
  247. int prices[26]; // ajándékok árai
  248. int i; // ciklusváltozó
  249. int price=0; // számla összege
  250. Child* northestChild = childBegin->next; // legészakabbi gyerek
  251. Child* iter; // ciklusváltozó
  252.  
  253. // az ajándékok árait tartalmazó fájl megnyitása, habakezeléssel nem foglalkozunk
  254. f = fopen("PRICE.DAT", "rb");
  255. // a 26 darab ajándék árainak beolvasása
  256. fread(prices, sizeof(unsigned int), 26, f);
  257. fclose(f);
  258.  
  259. // legészakabbi gyerek megkeresése
  260. for (iter = childBegin->next; iter->next != NULL; iter = iter->next){
  261. if(iter->y > northestChild->y){
  262. northestChild = iter;
  263. }
  264. }
  265.  
  266. // a szállítási költség kiszámítása amit a számla összegéhez adunk hozzá
  267. price += ((int)(northestChild->distance/1000)+1)*2;
  268. // levonjuk ezt a még felhasználható összegbõl
  269. northestChild->cash -= price;
  270. i = 0;
  271. // addig számlázzunk ki az ajándékokat amíg van rá elegendõ keret vagy amíg el nem fogynak a kért ajándékok
  272. while (northestChild->cash > prices[northestChild->gift[i]-'A'] && i<northestChild->gift_num){
  273. price += prices[northestChild->gift[i]-'A'];
  274. northestChild->cash -= prices[northestChild->gift[i]-'A'];
  275. i++;
  276. }
  277.  
  278. // visszatérünk a számla végösszegével
  279. return price;
  280. }
  281.  
  282.  
  283. int main(){
  284.  
  285. Base* southestBase; // legdélebbi bázis
  286. Base* baseBegin; // bázisok listája
  287. Child* childBegin; // gyerekek listája
  288. int price; //számla végösszege
  289. Base* jter, *jnext; // ciklusváltozók
  290. Child* iter; // ciklusváltozó
  291.  
  292. // bázisok beolvasása
  293. baseBegin = ReadBases();
  294. // legdélebbi bázis megkeresése
  295. southestBase = findSouthestBase(baseBegin);
  296. // legdélebbi bázishoz tartozó gyerekek megkeresése
  297. childBegin = searchChildrenSouth(baseBegin, southestBase);
  298. // távolságok kiszámítása és ez alapján a gyerekek rendezése
  299. calcDistAndSort(childBegin, southestBase);
  300. // legészakibb gyerek számlája összegének kiszámítása
  301. price = calcNorthestChildPrice(childBegin);
  302. printf("%d\n", price);
  303.  
  304.  
  305. // dinamikusan foglalt változók felszabadítása
  306. for (jter = baseBegin->next; jter->next != NULL; jter = jnext){
  307. jnext = jter->next;
  308. free(jter);
  309. }
  310. free(jnext);
  311.  
  312. for ( iter = childBegin->next; iter->next != NULL; iter = iter->next){
  313. free(iter->prev);
  314. }
  315. free(iter->prev);
  316. free(iter);
  317.  
  318. getchar();
  319.  
  320. return 0;
  321. }
Add Comment
Please, Sign In to add comment