Draw cube vertices with fewest number of steps

依然范特西╮ 提交于 2019-12-14 04:22:23

问题


What's the fewest number of steps needed to draw all of the cube's vertices, without picking up the pen from the paper?

So far I have reduced it to 16 steps:

0, 0, 0
0, 0, 1
0, 1, 1
1, 1, 1
1, 1, 0
0, 1, 0
0, 0, 0
1, 0, 0
1, 0, 1
0, 0, 1
0, 1, 1
0, 1, 0
1, 1, 0
1, 0, 0
1, 0, 1
1, 1, 1

I presume it can be reduced less than 16 steps as there are only 12 vertices to be drawn

You can view a working example in three.js javascript here: http://jsfiddle.net/kmturley/5aeucehf/show/


回答1:


Well I encoded a small brute force solver for this

  • the best solution is with 16 vertexes
  • took about 11.6 sec to compute
  • all is in C++ (visualization by OpenGL)

First the cube representation:

//---------------------------------------------------------------------------
#define a 0.5
double pnt[]=
    {
    -a,-a,-a, // point 0
    -a,-a,+a,
    -a,+a,-a,
    -a,+a,+a,
    +a,-a,-a,
    +a,-a,+a,
    +a,+a,-a,
    +a,+a,+a, // point 7
    1e101,1e101,1e101, // end tag
    };
#undef a
int lin[]=
    {
    0,1,
    0,2,
    0,4,
    1,3,
    1,5,
    2,3,
    2,6,
    3,7,
    4,5,
    4,6,
    5,7,
    6,7,
    -1,-1, // end tag
    };
// int solution[]={ 0, 1, 3, 1, 5, 4, 0, 2, 3, 7, 5, 4, 6, 2, 6, 7, -1 }; // found polyline solution
    //---------------------------------------------------------------------------
void draw_lin(double *pnt,int *lin)
    {
    glBegin(GL_LINES);
    for (int i=0;lin[i]>=0;)
        {
        glVertex3dv(pnt+(lin[i]*3)); i++;
        glVertex3dv(pnt+(lin[i]*3)); i++;
        }
    glEnd();
    }
//---------------------------------------------------------------------------
void draw_pol(double *pnt,int *pol)
    {
    glBegin(GL_LINE_STRIP);
    for (int i=0;pol[i]>=0;i++) glVertex3dv(pnt+(pol[i]*3));
    glEnd();
    }
//---------------------------------------------------------------------------

Now the solver:

//---------------------------------------------------------------------------
struct _vtx             // vertex
    {
    List<int> i;        // connected to (vertexes...)
    _vtx(){}; _vtx(_vtx& a){ *this=a; }; ~_vtx(){}; _vtx* operator = (const _vtx *a) { *this=*a; return this; }; /*_vtx* operator = (const _vtx &a) { ...copy... return this; };*/
    };
const int _max=16; // know solution size (do not bother to find longer solutions)
int use[_max],uses=0;   // temp line usage flag
int pol[_max],pols=0;   // temp solution
int sol[_max+2],sols=0; // best found solution
List<_vtx> vtx;         // model vertexes + connection info
//---------------------------------------------------------------------------
void _solve(int a)
    {
    _vtx *v; int i,j,k,l,a0,a1,b0,b1;
    // add point to actual polyline
    pol[pols]=a; pols++; v=&vtx[a];
    // test for solution
    for (l=0,i=0;i<uses;i++) use[i]=0;
    for (a0=pol[0],a1=pol[1],i=1;i<pols;i++,a0=a1,a1=pol[i])
     for (j=0,k=0;k<uses;k++)
        {
        b0=lin[j]; j++;
        b1=lin[j]; j++;
        if (!use[k]) if (((a0==b0)&&(a1==b1))||((a0==b1)&&(a1==b0))) { use[k]=1; l++; }
        }
    if (l==uses) // better solution found
     if ((pols<sols)||(sol[0]==-1))
      for (sols=0;sols<pols;sols++) sol[sols]=pol[sols];
    // recursion only if pol not too big
    if (pols+1<sols) for (i=0;i<v->i.num;i++) _solve(v->i.dat[i]);
    // back to previous state
     pols--; pol[pols]=-1;
    }
//---------------------------------------------------------------------------
void solve(double *pnt,int *lin)
    {
    int i,j,a0,a1;
    // init sizes
    for (i=0;i<_max;i++) { use[i]=0; pol[i]=-1; sol[i]=-1; }
    for(i=0,j=0;pnt[i]<1e100;i+=3,j++); vtx.allocate(j); vtx.num=j;
    for(i=0;i<vtx.num;i++) vtx[i].i.num=0;
    // init connections
    for(uses=0,i=0;lin[i]>=0;uses++)
        {
        a0=lin[i]; i++;
        a1=lin[i]; i++;
        vtx[a0].i.add(a1);
        vtx[a1].i.add(a0);
        }
    // start actual solution (does not matter which vertex on cube is first)
    pols=0; sols=_max+1; _solve(0);
    sol[sols]=-1; if (sol[0]<0) sols=0;
    }
//---------------------------------------------------------------------------

Usage:

solve(pnt,lin); // call once to compute the solution

glColor3f(0.2,0.2,0.2); draw_lin(pnt,lin); // draw gray outline
glColor3f(1.0,1.0,1.0); draw_pol(pnt,sol); // overwrite by solution to visually check correctness (Z-buffer must pass also on equal values!!!)

List

  • is just mine template for dynamic array
  • List<int> x is equivalent to int x[]
  • x.add(5) ... adds 5 to the end of list
  • x.num is the used size of list in entries
  • x.allocate(100) preallocate list size to 100 entries (to avoid relocations slowdowns)

solve(pnt,lin) algorithm

  1. first prepare vertex data

    • each vertex vtx[i] corresponds to point i-th point in pnt table
    • i[] list contains the index of each vertex connected to this vertex
  2. start with vertex 0 (on cube is irrelevant the start point

    • otherwise there would be for loop through every vertex as start point
  3. _solve(a)

    • it adds a vertex index to actual solution pol[pols]
    • then test how many lines is present in actual solution
    • and if all lines from lin[] are drawn and solution is smaller than already found one
    • copy it as new solution
    • after test if actual solution is not too long recursively add next vertex
    • as one of the vertex that is connected to last vertex used
    • to limit the number of combinations
  4. at the end sol[sols] hold the solution vertex index list

    • sols is the number of vertexes used (lines-1)

[Notes]

  • the code is not very clean but it works (sorry for that)
  • hope I did not forget to copy something


来源:https://stackoverflow.com/questions/25195363/draw-cube-vertices-with-fewest-number-of-steps

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!