10067, playing with wheels
Posted: Sun Mar 30, 2003 10:53 pm
this is not a popular problem but i need some help.
i represent every possible machine state as a vertex as an integer (0-9999)
there s an edge between 2 vertices if one can reach the other by one click
forbidden numbers are stored in a list to checked against validation.
my approach is to do a breath-first search on every test case to find the shortest path from start vertex to end vertex.
but i got MAX TIME EXCEED error. i dont see any way to make it more efficient , plz help.
thanks for looking
[cpp]
#include <iostream>
using namespace std;
#define MAXV 10000
#define MAXDEGREE 8
#define MAXQUEUELENGTH 10000
typedef struct {
int edges[MAXV+1][MAXDEGREE];
int degree[MAXV+1];
int nvertices;
int nedges;
}graph;
typedef struct {
int value[MAXQUEUELENGTH];
int start;
int size;
}queue;
void initialize_queue(queue *q);
void enqueue(queue *q, int k);
int dequeue(queue *q);
int size(queue *q);
void print_queue( queue *q);
void print_queue(queue *q)
{ cout <<"start ="<<q->start<<endl;
cout <<"size ="<<q->size<<endl;
int i;
for (i=q->start; i< q->start+q->size; i++)
cout <<q->value<<" ";
cout <<endl;
}
void read_graph(graph *g, bool directed, bool check_duplicate);
void initialize_graph(graph *g);
void insert_edge(graph *g, int x, int y, bool directed, bool check_duplicate);
void print_graph(graph *g);
void initialize_queue(queue *q)
{ q->start = 0;
q->size = 0;
}
void enqueue(queue *q, int k)
{ if (q->size >= MAXQUEUELENGTH)
cout <<"max capacity of queue reached"<<endl;
else
{ q->value[(q->start+q->size)%MAXQUEUELENGTH]=k;
q->size = (q->size+1)%MAXQUEUELENGTH;
}
}
int dequeue(queue *q)
{ if (q->size==0)
return -1;
int ans = q->value[q->start];
q->start = (q->start+1)%MAXQUEUELENGTH;
q->size--;
return ans;
}
int size(queue *q)
{ int ans;
ans = q->size;
return ans;
}
/*
void read_graph(graph *g, bool directed, bool check_duplicate)
{ int i;
int m;
int x, y, temp;
initialize_graph(g);
//scanf("%d %d", &(g->nvertices), &m); // num of vertices
//num of edges
cin >>temp ;
g->nvertices = temp;
cin >>m;
for (i=1; i<=m; i++)
{ cin>>x;
cin >> y;
insert_edge(g, x, y, directed, check_duplicate);
}
}
*/
void initialize_graph(graph *g)
{ int i;
g->nvertices = 0;
g->nedges = 0;
for (i=0; i<=MAXV; i++)
g->degree=0;
}
void insert_edge(graph *g, int x, int y, bool directed, bool check_duplicate)
{
int i;
bool found = false;
if (check_duplicate)
{ found = false;
for (i=0; i<g->degree[x]; i++)
{ if (g->edges[x]==y)
{ found = true;
cout<<"duplicate insert found"<<endl;
break;
}
}
}
if (!found)
{if (g->degree[x] > MAXDEGREE)
cout <<"Warning: insertion exceeds max degree"<<endl;
g->edges[x][g->degree[x]]=y;
g->degree[x]++;
if(directed == false)
insert_edge(g, y, x, true, check_duplicate);
else g->nedges++;
}
}
/*
void print_graph(graph *g)
{ cout <<"PRINT GRAPH"<<endl;
int i, j;
cout <<"g->nvertices ="<<g->nvertices<<endl;
cout <<"nedges ="<<g->nedges<<endl;
for (i=1; i<=g->nvertices; i++)
{ for (j=0; j<g->degree; j++)
cout <<i<<"-->"<<g->edges[j]<<" ";
cout <<endl;
}
int i;
for (i=0; i<=9999; i++)
cout <<g->degree<<" ";
}
*/
bool valid_edge(int edge, int barr[])
{ //return true;
//return false;
int i;
for (i=1; i<=barr[0]; i++)
{
if (edge == barr)
return false;
}
return true;
}
void process_vertex(int v)
{}
void process_edge(int from, int to)
{}
void bfs(graph *g, int start, int parent[], int barr[],int theEnd)
{ bool processed[MAXV];
bool discovered[MAXV];
// int parent[MAXV];
queue q;
int v;
int i;
//initialize the search
// cout <<"nvertices ="<<g->nvertices<<endl;
for (i=0; i< g->nvertices; i++)
{ processed = false;
discovered = false;
parent = -1;
}
initialize_queue(&q);
enqueue(&q, start);
discovered[start] = true;
while (size(&q)!=0)
{ v = dequeue(&q);
process_vertex(v);
processed[v] = true;
for (i=0; i<g->degree[v]; i++)
{ if(valid_edge(g->edges[v][i], barr)==true)
{
if (discovered[g->edges[v][i]] == false)
{ enqueue(&q, g->edges[v][i]);
discovered[g->edges[v][i]]=true;
parent[g->edges[v][i]] = v;
if (g->edges[v][i]==theEnd)
return;
}
if (processed[g->edges[v][i]] == false)
process_edge(v, g->edges[v][i]);
}
}
}
/*
for (i=1; i<=g->nvertices; i++)
cout << i<<" ";
cout <<endl;
for (i=1; i<=g->nvertices; i++)
cout << parent[i]<<" ";
cout<<endl;
*/
}
void main()
{// cout <<"hi"<<endl;
int i,j, temp1, temp2, temp3;
graph myGraph;
initialize_graph(&myGraph);
myGraph.nvertices = 10000;
for (i=0; i<=9999; i++)
{ for (j=1; j<=1000; j*=10)
{ temp1 = i/j;
temp2 = temp1%10;
if (temp2!=9)
temp3=i+j;
else
temp3=i-9*j;
insert_edge(&myGraph, i, temp3, false, true);
}
}
int n, start, end;
int bad;
int current, value, count, temp;
int f1, f2, f3, f4;
bool flag = false;
int parent[MAXV];
int barr[MAXV+1];
int theEnd;
cin >>n;
while (n!=0)
{ cin >> f1; cin>>f2; cin>>f3; cin>>f4;
start = 1000*f1+100*f2+10*f3+f4;
cin >> f1; cin>>f2; cin>>f3; cin>>f4;
end = 1000*f1+100*f2+10*f3+f4;
theEnd = end;
cin >> bad;
barr[0] = bad;
for (i=1; i<=bad; i++)
{
cin >> f1; cin>>f2; cin>>f3; cin>>f4;
temp = 1000*f1+100*f2+10*f3+f4;
barr[i] = temp;
}
bfs(&myGraph, start, parent, barr, theEnd);
count = 0;
current = end;
value = end;
while (value!=start && value!=-1)
{ current = value;
value = parent[current];
count++;
}
if (value==-1)
cout <<"-1"<<endl;
else cout <<count<<endl;
n--;
}
}
[/cpp]
i represent every possible machine state as a vertex as an integer (0-9999)
there s an edge between 2 vertices if one can reach the other by one click
forbidden numbers are stored in a list to checked against validation.
my approach is to do a breath-first search on every test case to find the shortest path from start vertex to end vertex.
but i got MAX TIME EXCEED error. i dont see any way to make it more efficient , plz help.
thanks for looking
[cpp]
#include <iostream>
using namespace std;
#define MAXV 10000
#define MAXDEGREE 8
#define MAXQUEUELENGTH 10000
typedef struct {
int edges[MAXV+1][MAXDEGREE];
int degree[MAXV+1];
int nvertices;
int nedges;
}graph;
typedef struct {
int value[MAXQUEUELENGTH];
int start;
int size;
}queue;
void initialize_queue(queue *q);
void enqueue(queue *q, int k);
int dequeue(queue *q);
int size(queue *q);
void print_queue( queue *q);
void print_queue(queue *q)
{ cout <<"start ="<<q->start<<endl;
cout <<"size ="<<q->size<<endl;
int i;
for (i=q->start; i< q->start+q->size; i++)
cout <<q->value<<" ";
cout <<endl;
}
void read_graph(graph *g, bool directed, bool check_duplicate);
void initialize_graph(graph *g);
void insert_edge(graph *g, int x, int y, bool directed, bool check_duplicate);
void print_graph(graph *g);
void initialize_queue(queue *q)
{ q->start = 0;
q->size = 0;
}
void enqueue(queue *q, int k)
{ if (q->size >= MAXQUEUELENGTH)
cout <<"max capacity of queue reached"<<endl;
else
{ q->value[(q->start+q->size)%MAXQUEUELENGTH]=k;
q->size = (q->size+1)%MAXQUEUELENGTH;
}
}
int dequeue(queue *q)
{ if (q->size==0)
return -1;
int ans = q->value[q->start];
q->start = (q->start+1)%MAXQUEUELENGTH;
q->size--;
return ans;
}
int size(queue *q)
{ int ans;
ans = q->size;
return ans;
}
/*
void read_graph(graph *g, bool directed, bool check_duplicate)
{ int i;
int m;
int x, y, temp;
initialize_graph(g);
//scanf("%d %d", &(g->nvertices), &m); // num of vertices
//num of edges
cin >>temp ;
g->nvertices = temp;
cin >>m;
for (i=1; i<=m; i++)
{ cin>>x;
cin >> y;
insert_edge(g, x, y, directed, check_duplicate);
}
}
*/
void initialize_graph(graph *g)
{ int i;
g->nvertices = 0;
g->nedges = 0;
for (i=0; i<=MAXV; i++)
g->degree=0;
}
void insert_edge(graph *g, int x, int y, bool directed, bool check_duplicate)
{
int i;
bool found = false;
if (check_duplicate)
{ found = false;
for (i=0; i<g->degree[x]; i++)
{ if (g->edges[x]==y)
{ found = true;
cout<<"duplicate insert found"<<endl;
break;
}
}
}
if (!found)
{if (g->degree[x] > MAXDEGREE)
cout <<"Warning: insertion exceeds max degree"<<endl;
g->edges[x][g->degree[x]]=y;
g->degree[x]++;
if(directed == false)
insert_edge(g, y, x, true, check_duplicate);
else g->nedges++;
}
}
/*
void print_graph(graph *g)
{ cout <<"PRINT GRAPH"<<endl;
int i, j;
cout <<"g->nvertices ="<<g->nvertices<<endl;
cout <<"nedges ="<<g->nedges<<endl;
for (i=1; i<=g->nvertices; i++)
{ for (j=0; j<g->degree; j++)
cout <<i<<"-->"<<g->edges[j]<<" ";
cout <<endl;
}
int i;
for (i=0; i<=9999; i++)
cout <<g->degree<<" ";
}
*/
bool valid_edge(int edge, int barr[])
{ //return true;
//return false;
int i;
for (i=1; i<=barr[0]; i++)
{
if (edge == barr)
return false;
}
return true;
}
void process_vertex(int v)
{}
void process_edge(int from, int to)
{}
void bfs(graph *g, int start, int parent[], int barr[],int theEnd)
{ bool processed[MAXV];
bool discovered[MAXV];
// int parent[MAXV];
queue q;
int v;
int i;
//initialize the search
// cout <<"nvertices ="<<g->nvertices<<endl;
for (i=0; i< g->nvertices; i++)
{ processed = false;
discovered = false;
parent = -1;
}
initialize_queue(&q);
enqueue(&q, start);
discovered[start] = true;
while (size(&q)!=0)
{ v = dequeue(&q);
process_vertex(v);
processed[v] = true;
for (i=0; i<g->degree[v]; i++)
{ if(valid_edge(g->edges[v][i], barr)==true)
{
if (discovered[g->edges[v][i]] == false)
{ enqueue(&q, g->edges[v][i]);
discovered[g->edges[v][i]]=true;
parent[g->edges[v][i]] = v;
if (g->edges[v][i]==theEnd)
return;
}
if (processed[g->edges[v][i]] == false)
process_edge(v, g->edges[v][i]);
}
}
}
/*
for (i=1; i<=g->nvertices; i++)
cout << i<<" ";
cout <<endl;
for (i=1; i<=g->nvertices; i++)
cout << parent[i]<<" ";
cout<<endl;
*/
}
void main()
{// cout <<"hi"<<endl;
int i,j, temp1, temp2, temp3;
graph myGraph;
initialize_graph(&myGraph);
myGraph.nvertices = 10000;
for (i=0; i<=9999; i++)
{ for (j=1; j<=1000; j*=10)
{ temp1 = i/j;
temp2 = temp1%10;
if (temp2!=9)
temp3=i+j;
else
temp3=i-9*j;
insert_edge(&myGraph, i, temp3, false, true);
}
}
int n, start, end;
int bad;
int current, value, count, temp;
int f1, f2, f3, f4;
bool flag = false;
int parent[MAXV];
int barr[MAXV+1];
int theEnd;
cin >>n;
while (n!=0)
{ cin >> f1; cin>>f2; cin>>f3; cin>>f4;
start = 1000*f1+100*f2+10*f3+f4;
cin >> f1; cin>>f2; cin>>f3; cin>>f4;
end = 1000*f1+100*f2+10*f3+f4;
theEnd = end;
cin >> bad;
barr[0] = bad;
for (i=1; i<=bad; i++)
{
cin >> f1; cin>>f2; cin>>f3; cin>>f4;
temp = 1000*f1+100*f2+10*f3+f4;
barr[i] = temp;
}
bfs(&myGraph, start, parent, barr, theEnd);
count = 0;
current = end;
value = end;
while (value!=start && value!=-1)
{ current = value;
value = parent[current];
count++;
}
if (value==-1)
cout <<"-1"<<endl;
else cout <<count<<endl;
n--;
}
}
[/cpp]