#include #include // // problème // #define n 41 // nombre de capteurs #define D1 1 // Les capteurs sont sur une ligne ou non. #define bi 0 // communication bidirectionnelle ou non. int x[n],y[n], // Le capteur i est en (x[i],y[i]) v[n][n], // v[i][0]=i,v[i][1], ... , v[i][n-1] est la liste des capteurs voisins de i rangés par distance croissante c[n][n], // c[i][r] est la contribution au coût du capteur i quand il atteint juste le capteur v[i][r] d[n][n], // d[i][j] est le nombre de capteurs atteints par le capteur i quand il atteint juste le capteur j. c1=1, c2=10; // coefficients des coûts de réception et d'émission // // sous-problème (ou solution réalisable) // /* rm[i] et rM[i] rayons mimimal et maximal d'émission du capteur i. Le rayon est le nombre d'autres capteurs atteints. Le branchement se fait en émettant du capteur i avec un rayon minimal r, ou non */ typedef struct { int cost, rm[n], rM[n], i, r; } sol; sol opti, S; // meilleure solution réalisable trouvée, sous-problème courant sol T, bonne;//une solution de S, bonne solution trouvée autrement (débogage) #define Rm S.rm #define RM S.rM #define Cost S.cost void affsol(sol S) { int i; for(i=0;iRM[i]-Rm[i]) return 0; if(Cost<=bonne.cost) return 1; // bonne est dans S et S.cost semble correct affsol(bonne); // Ça merde. On affiche tout et on arrête. affsol(T); affsol(S); printf("checkbonne erreur nbeval=%d\n",nbeval); if(1) exit(1); Cost=bonne.cost; return 1; } // // arbres binaires de recherche // typedef struct noeud noeud, *abr; struct noeud { sol S; abr fg,fd; } *lib=0; // liste des noeuds libres void getmem() { int i=1000; for(lib=calloc(i--,sizeof(*lib));i--;) lib[i].fg=i+1+lib; } #define A (*a) void rotg(abr*a) {abr b=A; A=b->fd, b->fd=A->fg, A->fg=b;}//rotation à gauche void rotd(abr*a) {abr b=A; A=b->fg, b->fg=A->fd, A->fd=b;}//rotation à droite #define ifd(c) if(!A c) break; else if(A c->CostCost>Cost) const int equi=0; // active ou non l'équilibrage des arbres void rangeabr(abr*a) // on ajoute un nouveau noeud contenant S { if(Cost>=opti.cost) return; for(;equi;) // on raccourcit la branche de l'arbre que l'on parcourt ifd() ifd(->fd) rotg(a), a=&A->fd; else ifd(->fd->fg) rotd(&A->fd), rotg(a), a=&A->fd->fg; else a=&A->fd; else ifg(->fg) rotd(a), a=&A->fg; else ifg(->fg->fd) rotg(&A->fg), rotd(a), a=&A->fg->fd; else a=&A->fg; while(A) a=A->Cost>Cost?&A->fg:&A->fd; if(!lib) getmem(); // On crée un nouveau s'il n'y a pas d'ancien if(!lib) lib=calloc(1,sizeof(*lib)); lib->S=S, lib->fd=0, A=lib, lib=A->fg, A->fg=0; } #undef ifd #undef ifg void oteminabr(abr*a) // On supprime le noeud le plus à gauche { if(equi) while(A->fg) rotd(a); // et on met son contenu dans S. while(A->fg) a=&A->fg; A->fg=lib, lib=A, A=lib->fd, S=lib->S; } #undef A // // évaluation // #define infini ((int)(~0u>>1)/n) int min(int a,int b) { return ab?a:b; } #define setmin(a,b) a=min(a,b) #define setmax(a,b) a=max(a,b) void afft(int*t,int i) { for(;i--;++t) if(*t==infini) printf(" inf"); else if(*t>infini/2) printf(" in"); else printf("%4d",*t); printf("\n"); } void affm(int(*t)[n ],int i) { printf("\n"); for(;i--;) afft(*t++,n ); } void affM(int(*t)[n*2],int i) { printf("\n"); for(;i--;) afft(*t++,n*2); } #define Afft(nom,s) printf(#nom),afft(nom,s) #define Affm(nom,s) printf(#nom),affm(nom,s) #define AffM(nom,s) printf(#nom),affM(nom,s) void eval() { int i, j, k, ii, jj, r, a, b, *p, nbc=n-1, ppv[n*2], fus[n*2], sui[n*2], ori[n*2][n*2], C[n*2][n*2]; nbeval++; for(i=n*2;i--;sui[fus[i]=i]=i-1) for(j=n*2;j--;) C[i][j]=infini; for(i=n;i--;) for(r=RM[i];r;r--) C[i][v[i][r]]=c[i][max(r,Rm[i])]; if(bi) for(i=n;i--;) for(j=n;j--;) if(C[i][j]==infini) C[j][i]=infini; for(i=n;i--;ppv[i]=v[i][r-1]) for(r=T.rM[i]=1;rk?&j:&k,*p>=n;) *p=ori[j][k]; for(i=nbc;i--;) { while(ppv[i]>=max(i,n)) ppv[i]=ori[i][ppv[i]]; if(i>=max(ppv[i],n)) ppv[ori[i][ppv[i]]]=ppv[i]; } for(a=0,i=n;i--;) if(a+=C[i][j=ppv[i]], T.rm[i]=max( Rm[i],d[i][j]), bi) setmax(T.rM[j],d[j][i]); if(Cost=T.cost=a,a>=opti.cost) return; for(a=0,i=n;i--;) b=c[i][r=T.rM[i]]-c[i][T.rm[i]], a=b>a?S.i=i,S.r=r,b:a; if(!a) opti=T; // la minoration est exacte } // // séparation // void sep1() { int r=S.r, a=c[S.i][r]; while(c[S.i][--r]==a) ; RM[S.i]=r; } void sep2() { int r=S.r ; Rm[S.i]=r; } void sepevalabr() { abr a=0; rangeabr(&a); sol T; while(a) { oteminabr(&a); int c=checkbonne(); T=S, sep1(), eval(), c-=checkbonne(); if(Cost=opti.cost) return; sol T[2]; T[1]=S, sep1(), eval(), T[0]=S; S=T[1], sep2(), eval(), T[1]=S; int i, j=T[0].cost=opti.cost) return; sol T=S; sep1(), eval(); swapS(&T), sep2(), eval(); if(T.costj // ccc[i][j][r], CCC(i,j,k) ou cc[i][j] représentent // le coût minimal d'un arbre couvrant les capteurs i..j avec // rayon(i)>=r, rayon(r)>=d(i,k) ou contenant l'arête i<-->j. void progdynD1bi() { int i, I, J, j, l, r, s, cc[n][n]; // [i..j]=[i..I]u[J..j] static int ccc[n][n][n]; // l=|j-i| s=(j-i)/|j-i|=J-I for(i=n;i--;) for(j=n;j--;) for(r=n;r--;) ccc[i][j][r]=infini; for(i=n;i--;Rm[i]=1) for(r=n;r--;cc[i][r]=infini) ccc[i][i][r]=c[i][r]; for(l=0;++l1;) setmin(ccc[i][j][r-1],ccc[i][j][r ] ); for(r=1;++r=r // aa[i][j] coût minimal d'une arborescence allant de ]i..j] ou [j..i[ vers i. void progdynD1mono() { int i, J, j, k, l, r, cc[n], ccc[n][n], aa[n][n]; for(i=n;i--;aa[i][i]=Rm[i]=0,cc[i]=infini) for(r=n;r--;) aa[i][r]=ccc[i][r]=infini; for(l=0;++l1;) setmin(ccc[J][r-1],ccc[J][r ] ); for(r=1;++r