http://acm.pku.edu.cn/JudgeOnline/problem?id=1137

Код:
#include <stdio.h>
#include <stdlib.h>

#define MAX_ROOMS 10
#define QUEUE_LEN 11000
#define CODENUM (1<<MAX_ROOMS)*MAX_ROOMS

typedef struct 
{
  int exnum,lightnum;
  int exit[MAX_ROOMS];
  int light[MAX_ROOMS];
} room;

FILE *inp;
int n,goal;
int queue[QUEUE_LEN],qhead,qtail;
short sit[CODENUM],back[CODENUM];
room r[MAX_ROOMS];
int caseno = 1;

/* Queue management */

void qinit() { qhead = qtail = 0; }

int qempty() { return qhead == qtail; }

void qpush(int pos, short dist, short bck)
{
  if(sit[pos] != -1)
    {
      /* printf("*** INPUT ERROR: multiple solutions!\n"); */
      return;
    }
  sit[pos] = dist;
  back[pos] = bck;
  queue[qtail] = pos;
  qtail = (qtail+1)%QUEUE_LEN;
  if(qtail == qhead)
    {
      printf("*** ERROR: Queue size too small!\n");
    }
}

int qpop()
{
  int tmp;

  if(qhead == qtail) return -1;
  tmp = queue[qhead];
  qhead = (qhead+1)%QUEUE_LEN;
  return tmp;
}

/* Converter for integer<->situation */

int situation2int(int pos, int *light)
{
  int b,cod,i;
  
  for(code=i=0,b=1;i<n;i++,b<<=1)
    if(light[i]) cod += b;
  return cod*n+pos;
}

void int2situation(int cod, int *pos, int *light)
{
  int i;

  *pos = cod%n;
  cod /= n;
  for(i=0;i<n;i++,cod>>=1)
    light[i] = cod & 1;
}
 
void print_sol(int cod)
{
  if(back[cod] == -1) return;
  if(back[cod] < n) /* movement */
    {
      print_sol(n*(cod/n)+back[cod]);
      printf("- Move to room %d.\n",cod%n+1);
    }
  else /* switch light */
    {
      print_sol(((cod/n)^(1<<(back[cod]-n)))*n+cod%n);
      printf("- Switch %s light in room %d.\n",
	     (cod/n)&(1<<(back[cod]-n))?"on":"off",back[cod]-n+1);
    }
}

/* We solve the problem by brute force. By breadth-first search we
   enumerate all possible cases */

void solve_case()
{
  int i;
  int light[MAX_ROOMS],pos,cod,dist;

  for(i=0;i<(1<<n)*n;i++) sit[i] = -1;
  pos = 0; light[0] = 1;
  for(i=1;i<n;i++) light[i] = 0;
  cod = situation2int(pos,light);
  dist = 0;
  qinit();
  qpush(cod,dist,-1);
  while(!qempty())
    {
      cod = qpop(); dist = sit[cod];
      int2situation(cod,&pos,light);

      /* compute successors */

      /* a) move into another room */

      for(i=0;i<r[pos].exnum;i++)
	if(light[r[pos].exit[i]]) /* enter only rooms that have light */
	  {
	    cod = situation2int(r[pos].exit[i],light);
	    qpush(cod,dist+1,pos);
	  }

      /* b) turn on/off lights */

      for(i=0;i<r[pos].lightnum;i++)
	if(r[pos].light[i] != pos) /* do not turn off light in current room */
	{
	  light[r[pos].light[i]] = 1-light[r[pos].light[i]];
	  cod = situation2int(pos,light);
	  qpush(cod,dist+1,n+r[pos].light[i]);
	  light[r[pos].light[i]] = 1-light[r[pos].light[i]];
	}
    }

  /* output the solution */

  printf("Villa #%d\n",caseno++);
  for(i=0;i<n-1;i++) light[i] = 0;
  light[n-1] = 1;
  cod = situation2int(n-1,light);
  if(sit[cod] == -1)
    printf("The problem cannot be solved.\n\n");
  else
    {
      printf("The problem can be solved in %d steps:\n",sit[cod]);
      print_sol(cod);
      printf("\n");
    }
}

/* read in the data */

void skip_line() { while(getc(inp) >= ' '); }

int comp_int(const void *a, const void *b) 
{ 
  return *((const int *)a)-*((const int *)b);
}

int read_case()
{
  int i,d,s,a,b;

  fscanf(inp,"%d %d %d",&n,&d,&s); skip_line();
  if(n == 0) return 0;
  for(i=0;i<n;i++)
    r[i].exnum = r[i].lightnum = 0;
  for(i=0;i<d;i++)
    {
      fscanf(inp,"%d %d",&a,&b); skip_line();
      r[a-1].exit[r[a-1].exnum++] = b-1;
      r[b-1].exit[r[b-1].exnum++] = a-1;
    }
  for(i=0;i<s;i++)
    {
      fscanf(inp,"%d %d",&a,&b); skip_line();
      r[a-1].light[r[a-1].lightnum++] = b-1;
    }
  /* This is completely unnecessary, but gives nicer (= ordered) output
     later */
  for(i=0;i<n;i++)
    {
      qsort(r[i].exit,r[i].exnum,sizeof(int),comp_int);
      qsort(r[i].light,r[i].lightnum,sizeof(int),comp_int);
    }
  return 1;
}

int main()
{
  inp = stdin; // fopen("villa.in","r");
  while(read_case()) solve_case();
  // fclose(inp);
  return 0;
}