20 ος ΠΑΝΕΛΛΗΝΙΟΣ ΔΙΑΓΩΝΙΣΜΟΣ ΠΛΗΡΟΦΟΡΙΚΗΣ ΛΥΣΕΙΣ ΘΕΜΑΤΩΝ ΤΕΛΙΚΗΣ ΦΑΣΗΣ Με εξαίρεση το 3ο θέμα, στα 2 πρώτα, υποβλήθηκαν περισσότερες από μία βέλτιστες λύσεις (100% σημείων επιτυχίας). Από αυτές τελείως ενδεικτικά, παραθέτουμε μία για κάθε θέμα. Data Blocks (Αρσένης Γεράσιμος 2ο ΓΕΛ Μοσχάτου) /* USER: gars6at LANG: C TASK: blocks */ #include <stdio.h> #include <stdlib.h> #define MAX 70000 int comp(const void *i, const void *j) return *(long *)i-*(long *)j; int main() FILE *fin=fopen("blocks.in", "r"), *fout=fopen("blocks.out", "w"); long blocks[max], n, i, j; fscanf(fin, "%ld", &n); fclose(fin); for (i=2, j=0; i*i<=n; i++) if (n%i==0) blocks[j]=i; j++; if (i!=n/i) blocks[j]=n/i; j++; blocks[j]=1; j++; qsort(blocks, j, sizeof(long), comp); fprintf(fout, "%ld\n", j); for (i=0; i<j; i++) fprintf(fout, "%ld\n", blocks[i]); fclose(fout); return 0; +30-210-3300999, fax +30-210-3301893 E-mail: epy@epy.gr, Web: www.epy.gr 1 από 9
Sonar (Παναγιωτάκος Γεώργιος 1ο ΓΕΛ Σπάρτης) /* USER: gpan2lak LANG: C++ TASK: sonar */ #include <iostream> #include <fstream> #include <list> using namespace std; int n,m1,m2; class Pt public: int x,y; ; bool operator<(pt a,pt b) if(a.x==b.x) return a.y<b.y; else return a.x<b.x; list<pt> L; int main() //input ifstream fin("sonar.in"); ofstream fout("sonar.out"); fin >> n >> m1 >> m2; // //main prog int u,i; Pt a; for(u=0;u<m1;u++) fin >> a.x >> i; a.y=n+1-i; L.push_back(a); for(u=0;u<m2;u++) fin >> a.y >> i; a.x=n+1-i; +30-210-3300999, fax +30-210-3301893 E-mail: epy@epy.gr, Web: www.epy.gr 2 από 9
L.push_back(a); L.sort(); Pt last; last.x=-1; last.y=-1; list<pt>::iterator l; for(l=l.begin();l!=l.end();l++) if((*l).x==last.x && (*l).y==last.y) l=l.erase(l); l--; continue; last.x=(*l).x; last.y=(*l).y; fout << L.size() << "\n"; for(l=l.begin();l!=l.end();l++) fout << (*l).x << " " << (*l).y << "\n"; return 0; +30-210-3300999, fax +30-210-3301893 E-mail: epy@epy.gr, Web: www.epy.gr 3 από 9
Code (Για τη λύση του συγκεκριμένου προβλήματος κύκλος Hamilton - υπάρχουν περισσότερες από μία ορθές λύσεις. Ο χρόνος που απαιτείται για την εξαγωγή των αποτελεσμάτων, εξαρτάται από τα test cases. Επειδή για τα συγκεκριμένα test cases κανένας μαθητής δεν έδωσε λύση που να λύνει τουλάχιστον το 50% αυτών εντός χρόνου, δίνουμε στη δημοσιότητα μια από τις δυνατές λύσεις που για τα συγκεκριμένα tests, απαιτεί χρόνο πολύ μικρότερο από 20 sec για πάνω από το 50% των tests) /* * Solution for 'code' --- PDP 20, April 21, 2008 * Dimitris Fotakis <fotakis@aegean.gr> * Nikolaos S. Papaspyrou <nickie@softlab.ntua.gr> */ #define DEBUG #ifdef DEBUG #define debug(...) fprintf(stderr, VA_ARGS ) #else #define debug(...) do ; while(0) #define NDEBUG #endif #include <assert.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <math.h> #include <time.h> #include <sys/types.h> #define NILL (-1) #define INF ((long) (LONG_MAX)) #define NONE (-1) #define VISITED 0 #define UNVISITED 1 #define EXPLORED 2 void randomize () time_t t1; (void) time(&t1); srand((long) t1); /* use time in seconds to set the seed */ /* Implements a FIFO queue for use with BFS */ typedef struct _elem int id; struct _elem *next; elem; +30-210-3300999, fax +30-210-3301893 E-mail: epy@epy.gr, Web: www.epy.gr 4 από 9
elem *head = NULL, *tail = NULL; void addtoqueue (int v) elem *last; if ((last = (elem *)malloc(sizeof(elem))) == NULL) fprintf(stderr, "Out of memory!\n"); last->id = v; last->next = NULL; if (tail!= NULL) tail->next = last; tail = last; if (head == NULL) head = last; int extractfromqueue () elem *first; int res; if (head == NULL) return(nill); first = head; res = first->id; head = first->next; if (head == NULL) tail = NULL; free(first); return res; /* Data type definitions for adjacency list */ typedef struct _edge int id; struct _edge *next; Edge; typedef struct _node Edge *head; Edge *tail; int previncycle; int nextincycle; int incycle; int degree; Node; typedef Node * List; /* Creates an edge */ Edge *initedge (int id) Edge *e; +30-210-3300999, fax +30-210-3301893 E-mail: epy@epy.gr, Web: www.epy.gr 5 από 9
if ((e =(Edge *)malloc(sizeof(edge))) == NULL) fprintf(stderr, "Out of memory!\n"); e->next = NULL; e->id = id; return e; /* Reads a graph from filename and creates its adjacency list */ /* Initializes N (#vertices) and M (#edges) and returns the list */ List readgraph(file *fp, int *N, int *M) Edge *lastv1, *lastv2; int i, n = 0, v1, v2; List G; fscanf(fp, "%d\n", M); if ((G = (List) malloc((*m)*sizeof(node))) == NULL) fprintf(stderr, "Out of memory!\n"); for (i = 0; i < *M; i++) G[i].head = G[i].tail = NULL; G[i].nextInCycle = G[i].prevInCycle = NONE; G[i].degree = G[i].inCycle = 0; for (i = 0; i < *M; i++) fscanf(fp, "%d %d\n", &v1, &v2); if (n < v1) n = v1; if (n < v2) n = v2; v1--; v2--; lastv1 = initedge(v2); G[v1].degree++; lastv2 = initedge(v1); G[v2].degree++; if (G[v1].head == NULL) G[v1].head = G[v1].tail = lastv1; else G[v1].tail = G[v1].tail->next = lastv1; if (G[v2].head == NULL) G[v2].head = G[v2].tail = lastv2; else G[v2].tail = G[v2].tail->next = lastv2; *N = n; if ((G = (List) realloc(g, n*sizeof(node))) == NULL) fprintf(stderr, "Error in realloc!\n"); return G; +30-210-3300999, fax +30-210-3301893 E-mail: epy@epy.gr, Web: www.epy.gr 6 από 9
bool degree_lt_2 (List G, int N) int i; for (i = 0; i < N; i++) if (G[i].degree < 2) return true; return false; bool not_connected (List G, int N) int s, cc = 0, v; Edge *e; int *m; if ((m = (int *) malloc(n*sizeof(int))) == NULL) fprintf(stderr, "Out of memory!\n"); for (s = 0; s < N; s++) m[s] = UNVISITED; for (s = 0; s < N; s++) if (m[s] == EXPLORED) continue; addtoqueue(s); m[s] = VISITED; cc++; while ((v = extractfromqueue())!= NILL) m[v] = EXPLORED; for (e = G[v].head; e!= NULL; e = e->next) if (m[e->id] == UNVISITED) addtoqueue(e->id); m[e->id] = VISITED; return cc > 1; int extension_rotation (List G, int N) long iter, maxiter = (long) (((double) N)*(pow(log((double)N), 4))); int invert = 1, cur, last, rotv, i, k, ofs, tmp, first; Edge *p; cur = rand() % N; G[cur].inCycle = 1; first = cur; for (iter=0; invert <= N && iter < maxiter; iter++) /* complete a Hamiltonian path to a cycle */ if (invert == N) for (p = G[cur].head; p!= NULL; p = p->next) if (G[p->id].prevInCycle == NONE) +30-210-3300999, fax +30-210-3301893 E-mail: epy@epy.gr, Web: www.epy.gr 7 από 9
G[cur].nextInCycle = p->id; G[p->id].prevInCycle = cur; return(invert+1); /* extension phase */ for (p = G[cur].head, k = 0;!k && p!= NULL; p = p->next) if (G[p->id].inCycle == 0) G[p->id].inCycle = 1; G[p->id].prevInCycle = cur; G[cur].nextInCycle = p->id; cur = p->id; invert++; k = 1; /* rotation phase */ if (!k) do ofs = (rand() % G[cur].degree); for (p = G[cur].head; ofs > 0; ofs--) p = p->next; rotv = p->id; while (rotv == G[cur].prevInCycle); if (rotv == first) first = G[rotv].nextInCycle; G[rotv].nextInCycle = NONE; G[rotv].prevInCycle = cur; G[cur].nextInCycle = rotv; G[first].prevInCycle = NONE; cur = rotv; else last = G[rotv].nextInCycle; G[rotv].nextInCycle = cur; G[cur].nextInCycle = rotv; i = G[last].nextInCycle; G[last].nextInCycle = NONE; G[last].prevInCycle = i; do tmp = G[i].nextInCycle; G[i].nextInCycle = G[i].prevInCycle; G[i].prevInCycle = tmp; i = tmp; while (i!= rotv); cur = last; return invert; int main () FILE * fin = fopen("code.in", "rt"); FILE * fout = fopen("code.out", "wt"); +30-210-3300999, fax +30-210-3301893 E-mail: epy@epy.gr, Web: www.epy.gr 8 από 9
int N, M, res, i; int iter = 0, maxiter = 40; List G; assert(fin!= NULL); assert(fout!= NULL); G = readgraph(fin, &N, &M); ΕΛΛΗΝΙΚΗ ΕΤΑΙΡΕΙΑ ΕΠΙΣΤΗΜΟΝΩΝ ΚΑΙ if (degree_lt_2(g, N) not_connected(g, N)) fprintf(fout, "0\n"); else randomize(); do if ((res = extension_rotation(g, N)) == N+1) break; iter++; for (i = 0; i < N; i++) G[i].nextInCycle = G[i].prevInCycle = NONE; G[i].inCycle = 0; while (iter < maxiter); if (res == N+1) fprintf(fout, "1\n"); for (i = G[0].nextInCycle; i!= 0; i = G[i].nextInCycle) fprintf(fout, "%d\n", i+1); else fprintf(fout, "0\n"); fclose(fin); fclose(fout); return 0; +30-210-3300999, fax +30-210-3301893 E-mail: epy@epy.gr, Web: www.epy.gr 9 από 9