当前位置: 首页 > 知识库问答 >
问题:

在知道墙壁位置的同时计算房间数

霍襦宗
2023-03-14

这个问题是关于C生成器6的代码。赏金对标准C算法感兴趣,以解决给定标准化输入的问题(有关详细信息,请参阅此文)。

txt文件,它也代表我在数组中的数据:

11001 0110 1101 0110 1100 0101 0110
1110 1001 0110 1011 1010 1111 1010
1000 0101 0011 1110 1010
1011 1101 0101 0001 0101 0010 1011

txt的解释:< br > The文件中的数字是房间墙壁的4位表示,设置位表示墙壁。墙位按顺时针顺序排列,最高有效位是西墙。例如,1101代表一个房间,其中:

  • 最重要位置的设置位表示向西的墙
  • 下一个最重要位置的设置位表示向北的墙
  • 未设置的位表示东边没有墙
  • 最低有效位置的设置位表示向南有一堵墙

鉴于:

  1. 房间的外墙总会有一面墙
  2. 内墙将始终在两个房间中表示(在示例中,因为(1,1)的房间是1101,它包含一堵墙向南,所以(1,2)1110的房间必须包含一堵墙向北
  3. 永远不会超过numeric_limits

我被要求发布我的代码,所以这里是:
我试图解决这个问题,但我遇到了EAAccess违规,有人能告诉我我做错了什么吗?

  int rn=0,z=0, global=0,coord[15],c[411],b1[411];

void peruse ( int i, int j,int* bb)
{
bool top=false,bottom=false,right=false,left=false;
//truth checks

if (bb[i*m+j]<1000)  left=true;

if (bb[i*m+j]<100)   top=true; else if (bb[i*m+j]-1000<100)   top=true;

if (bb[i*m+j]<10)    right=true; else
if ( (bb[i*m+j]-100<10) || (bb[i*m+j]-1000<10) || (bb[i*m+j]-100<10) ) right=true;

if (bb[i*m+j]<1)   bottom=true; else
if ( (bb[i*m+j]-10<1) || (bb[i*m+j]-100<1) || (bb[i*m+j]-1000<1) ||(bb[i*m+j]-100<1))
bottom=true;
//marc

if  (left)
{
c[i*m+j]=c[i*m+j]+1000; // EAaccessViolation i dont know why.....
peruse(i,j-1,c);
}
if (top)
{
c[i*m+j]=c[i*m+j]+100;
peruse(i-1,j,c);
}
if (right)
{
c[i*m+j]=c[i*m+j]+10;
peruse(i,j+1,c);
}
if (bottom)
{
c[i*m+j]=c[i*m+j]+1;
peruse(i+1,i,c);
}
 if ( !(left) && !(top) && !(right) && !(bottom) )
 {
  bb[411]++;



 }
}


void __fastcall TForm1::Button7Click(TObject *Sender)
{
b1[411]=0;

 for(int i=0;i<n;i++)
    for (int j=0;j<m;j++)
          {
           b1[i*m+j]=b[i][j];
           c[i*m+j]=b[i][j];
          }
  peruse (1,1,b1);

 ShowMessage("Nr. "+IntToStr(b1[411]) );
}

共有3个答案

岳凯康
2023-03-14

你的代码几乎没有问题禁止正确的调试形式第三方,比如关于它如何工作的信息不足,未定义的变量(m,n,b)数组溢出(大量访问[411],而大小只有411而不是412),阻止任何人甚至开始尝试(让人怀疑代码是否真的有用,值得花时间)。我也很好奇,所以在这里,我在BDS2006 Turbo C(BCB6的继任者,所以这个代码也应该在那里工作)中简单的未优化的尝试来完成这个任务。

[房间. h]

//---------------------------------------------------------------------------
#ifndef _rooms_h
#define _rooms_h
//---------------------------------------------------------------------------
class rooms
    {
public:
    // variables
    int xs,ys;          // map resolution
    DWORD **map;        // map[xs][ys]

    enum
        {
        _W=8,
        _N=4,
        _E=2,
        _S=1
        };

    // internals
    rooms();
    ~rooms();
    void _free();                                       // release map memory

    // inteface
    void resize(int _xs,int _ys);                       // realloc map to new resolution
    void set(AnsiString txt);                           // copy txt to map
    void draw(TCanvas *scr,int x,int y,int sz);         // draw map on Canvas at (x,y) with grid size sz
    int  count();                                       // count rooms
    };
//---------------------------------------------------------------------------
     rooms::rooms()     { map=NULL; xs=0; ys=0; }
     rooms::~rooms()    { _free(); }
//---------------------------------------------------------------------------
void rooms::_free()
    {
    if (map)
        {
        for (int x=0;x<xs;x++)
         if (map[x])
          delete[] map[x];
        delete[] map;
        }
    map=NULL; xs=0; ys=0;
    }
//---------------------------------------------------------------------------
void rooms::resize(int _xs,int _ys)
    {
    if ((xs==_xs)&&(ys==_ys)) return;
    _free();
    xs=_xs; ys=_ys;
    map=new DWORD*[xs];
    for (int x=0;x<xs;x++)
     map[x]=new DWORD[ys];
    }
//---------------------------------------------------------------------------
void rooms::set(AnsiString txt)
    {
    int i,l,x,y,n0,n1;
    l=txt.Length(); if (!l) return;
    // count eof lines (ys)
    for (y=0,i=1;i<=l;i++)
     if ((txt[i]==13)||(txt[i]==10))
        {
        y++;
        if (i<l)
         if ((txt[i+1]==13)||(txt[i+1]==10)) i++;
        }
     if ((txt[l]!=13)&&(txt[l]!=10)) y++;   // handle missing last eof
    // count numbers per line (xs)
    for (n1=0,x=0,i=1;i<=l;i++)
        {
        n0=n1; n1=0;
        if ((txt[i]=='0')||(txt[i]=='1')) n1=1;
        if ((txt[i+1]==13)||(txt[i+1]==10)) break;
        if ((!n0)&&(n1)) x++;
        }
    // copy data
    resize(x,y);
    for (x=0,y=0,i=1;i<=l;)
        {
        // skip spaces
        while ((i<=l)&&(txt[i]!='0')&&(txt[i]!='1')) i++;
        // read 4 bit bin number
        n0=  0; if (i>l) break; if (txt[i]=='1') n0|=1; i++;
        n0<<=1; if (i>l) break; if (txt[i]=='1') n0|=1; i++;
        n0<<=1; if (i>l) break; if (txt[i]=='1') n0|=1; i++;
        n0<<=1; if (i>l) break; if (txt[i]=='1') n0|=1; i++;
        map[x][y]=n0;
        x++; if (x>=xs) { x=0; y++; if (y>=ys) break; }
        }
    // clear the rest in case of error in data
    if ((y<ys)&&(x<xs)) for (;;)
        {
        map[x][y]=0;
        x++; if (x>=xs) { x=0; y++; if (y>=ys) break; }
        }
    }
//---------------------------------------------------------------------------
void rooms::draw(TCanvas *scr,int x0,int y0,int sz)
    {
    int x,y,xx,yy;
    DWORD a;

    scr->Brush->Color=clDkGray;
    scr->Brush->Style=bsSolid;
    scr->FillRect(Rect(x0,y0,x0+xs*sz,y0+ys*sz));

    scr->Pen->Color=clBlue;
    scr->Pen->Width=5;
    scr->Font->Color=clBlack;
    scr->Brush->Style=bsClear;
    for (xx=x0,x=0;x<xs;x++,xx+=sz)
     for (yy=y0,y=0;y<ys;y++,yy+=sz)
        {
        a=map[x][y]&15;
        if (DWORD(a&_W)) { scr->MoveTo(xx   ,yy   ); scr->LineTo(xx   ,yy+sz); }
        if (DWORD(a&_N)) { scr->MoveTo(xx   ,yy   ); scr->LineTo(xx+sz,yy   ); }
        if (DWORD(a&_E)) { scr->MoveTo(xx+sz,yy   ); scr->LineTo(xx+sz,yy+sz); }
        if (DWORD(a&_S)) { scr->MoveTo(xx   ,yy+sz); scr->LineTo(xx+sz,yy+sz); }
        scr->TextOutA(xx+(sz>>1),yy+(sz>>1),map[x][y]>>4);
        }
    scr->Brush->Style=bsSolid;
    scr->Pen->Width=1;
    }
//---------------------------------------------------------------------------
int  rooms::count()
    {
    int x,y,i,i0,i1,w0,w1,n,e;
    // each block is a separate room
    for (n=0,x=0;x<xs;x++)
     for (y=0;y<ys;y++,n+=16)
        {
        map[x][y]&=  0x0000000F;    // low 4 bits are walls
        map[x][y]|=n&0xFFFFFFF0;    // rest is room index
        } n>>=4;
    // reindex all indexes i0 to i1
    #define map_reindex(i0,i1)                      \
        for (x=0;x<xs;x++)                          \
         for (y=0;y<ys;y++)                         \
          if (DWORD(map[x][y]&0xFFFFFFF0)==i0)      \
            {                                       \
            map[x][y]&=   0x0000000F;               \
            map[x][y]|=i1&0xFFFFFFF0;               \
            }
    // loop until no change has occured
    for (e=1;e;)
        {
        e=0;
        // merge columns
        for (x=0;x<xs;x++)
         for (y=1;y<ys;y++)
            {
            w0=map[x][y-1]&0x0000000F;
            i0=map[x][y-1]&0xFFFFFFF0;
            w1=map[x][y  ]&0x0000000F;
            i1=map[x][y  ]&0xFFFFFFF0;
            if ((i0!=i1)&&(DWORD(w0&_S)==0)&&(DWORD(w1&_N)==0)) { map_reindex(i0,i1); n--; e=1; }
            }
        // merge rows
        for (y=0;y<ys;y++)
         for (x=1;x<xs;x++)
            {
            w0=map[x-1][y]&0x0000000F;
            i0=map[x-1][y]&0xFFFFFFF0;
            w1=map[x  ][y]&0x0000000F;
            i1=map[x  ][y]&0xFFFFFFF0;
            if ((i0!=i1)&&(DWORD(w0&_E)==0)&&(DWORD(w1&_W)==0)) { map_reindex(i0,i1); n--; e=1; }
            }
        }           

    return n;
    #undef map_reindex
    }
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

[无任何组件的单窗口VCL表单应用程序C源代码]

//$$---- Form CPP ----
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "rooms.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
Graphics::TBitmap *bmp; // back buffer
int xs,ys;              // actual window resolution
rooms map;              // map of rooms
//---------------------------------------------------------------------------
void draw()
    {
    int x,y,sz;
    // clear bachground
    bmp->Canvas->Brush->Color=clBlack;
    bmp->Canvas->Brush->Style=bsSolid;
    bmp->Canvas->FillRect(Rect(0,0,xs,ys));
    // compute grid size
    x=(xs-20)/map.xs; sz=x;
    y=(ys-20)/map.ys; if (x>y) sz=y;
    // and map position so it is centered
    x=(xs-(sz*map.xs))>>1;
    y=(ys-(sz*map.ys))>>1;
    // render to backbuffer (avoid flickering)
    map.draw(bmp->Canvas,x,y,sz);
    // render backbuffer to window
    Form1->Canvas->Draw(0,0,bmp);
    }
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
    {
    // init backbuffer
    bmp=new Graphics::TBitmap;
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    // init map
    map.set("1101 0110 1101 0110 1100 0101 0110\r\n1110 1001 0110 1011 1010 1111 1010\r\n1000 0101 0011 1110 1011 1110 1010\r\n1011 1101 0101 0001 0101 0011 1011\r\n");
    Caption=map.count();    // result count is in the Window Caption
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender) { delete bmp; }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender) { draw(); }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
    {
    // get actual window size
    xs=ClientWidth;
    ys=ClientHeight;
    // resize backbufer and force redraw
    bmp->SetSize(xs,ys);
    draw();
    }
//---------------------------------------------------------------------------

我的解算器背后的想法很简单:

>

  • 按不同的房间号对每个网格单元格进行 ID

    记住单元格计数为n

    合并所有相邻的房间,房间之间没有任何墙

    因此,在所有房间中循环,如果任何相邻单元没有墙壁,并且有不同的房间,请重新索引其房间编号,以便展台房间具有相同的房间。同时减少房间计数器n

    循环#2,直到没有发生重新索引

    https://imgs.xnip.cn/cj/n/14/c2cd5b4e-f588-4c72-bad1-640a0411f097.png" width="100%" height="100%" />

    [注]

    不要忘记在 IDE 中创建适当的事件,而不仅仅是复制代码,否则它将不起作用。

  • 索寒
    2023-03-14

    所以说实话,我真的很想尝试解决这个问题。所以我想说,你在这方面已经做出了勇敢的努力,只是继续向你展示如何做到这一点。我假设您可以提供以下算法:

    1. 以二进制格式读入的输入数字(因此“1101”将作为十进制数字“13”读取)
    2. 常量向量中的所有这些数字

    我们将使用<代码>向量

    我们的解决方案将围绕一个功能构建,该功能包含两个“房间”,其间没有墙;以便:

    1. 一个房间还没有标签,在这种情况下,它将与另一个房间的标签相同
    2. 两个房间共享一个标签,在这种情况下不会采取任何行动
    3. 一个房间的标签较小,在这种情况下,较大标签的所有房间都将被分配较小的标签

    关于这个函数的一个重要注意事项,我使用一元加号运算符从L值整数构造一个R值int

    void generate(vector<int>& temp, int& target, const size_t width, const size_t i) {
        const auto replacement = temp[i];
    
        if (target > replacement) {
            replace(begin(temp), next(begin(temp), min(size(temp), i + width - 1)), target, replacement);
        } else {
            target = replacement;
        }
    }
    

    使用该代码,我们能够:

    for (size_t i = 0U; i < size(rooms); ++i) {
        const auto toWest = (rooms[i] & 0b1000) == 0;
        const auto toNorth = (rooms[i] & 0b100) == 0;
        const auto toEast = (rooms[i] & 0b10) == 0;
        const auto toSouth = (rooms[i] & 0b1) == 0;
        const auto west = toWest && temp[i - 1] != 0 ? temp[i - 1] : numeric_limits<int>::max();
        const auto north = toNorth && temp[i - width] != 0 ? temp[i - width] : numeric_limits<int>::max();
        const auto east = toEast && temp[i + 1] != 0 ? temp[i + 1] : numeric_limits<int>::max();
    
        temp[i] = min({ temp[i] != 0 ? temp[i] : numeric_limits<int>::max(), result + 1, west, north, east });
    
        if (temp[i] == result + 1) ++result;
    
        if (toWest) generate(temp, temp[i - 1], width, i);
        if (toNorth) generate(temp, temp[i - width], width, i);
        if (toEast) generate(temp, temp[i + 1], width, i);
        if (toSouth) temp[i + width] = temp[i];
    }
    

    < kbd >实例

    文增
    2023-03-14

    这是在图形中查找已连接组件总数的典型问题。

    让我通过关注以下几点来帮助你形象化这个类比,记住我们在这里处理的是无向图。

    1.In 图中,我们有各种顶点,如果它们之间有一条边,则说两个顶点彼此相邻。就像你的城堡一样,如果一个细胞可以通向另一个细胞,那么两个细胞彼此相邻。

    2. 在图形中,如果两个顶点之间存在使用边的路径,则我们有两个顶点属于同一连接组件。就像你的城堡,两个细胞属于同一个房间号,如果一个细胞可以通过遵循一个细胞的路径来导致另一个。

    3.在图中,我们有连接的组件,这样连接的组件由顶点组成,这样连接组件的每两个顶点之间都有一条路径。就像你的城堡里我们有房间一样,同一个房间的每两个单元之间都有一条细胞路径。

    现在,如果你还想知道如何构建图表,这很简单。

    顶点的数量将是NxM(对于大小为N行和M列的城堡),它等于像元的数量。

    只需按顺序对单元格进行编号,如果两个单元格相邻,则单元格a(表示顶点a)单元格b(顶点b)之间有一条边缘。

    现在,通过在构建的图形上应用bfs或dfs算法,可以轻松计算房间总数。

    算法在我提供的第一个链接中描述。

     类似资料:
    • 问题内容: 我想通过查看算法的运行时性能来测试哪种数据结构是最佳的,我该怎么做? 例如我已经有一个; 假设我有我的,我想知道下面的语句需要多长时间来执行:。 我该如何计时? 谢谢! 问题答案: 首先看一下我对这个问题的回答;它包含一个可移植的(windows/linux)函数,以毫秒为单位获取时间。 接下来,执行以下操作: 全做完了!(请注意,我没有尝试编译它)

    • 我正在看Android的新ARCore库。它有检测水平表面的方法,但没有检测垂直表面或墙壁的方法。 我实际上试图使示例应用程序检测墙壁,但我有很多问题。 在ARCore中是否有一种本机或非本机检测垂直表面的方法?

    • 我已经尝试解决了平滑的玩家-墙壁碰撞的问题,这样玩家可以沿着墙壁滑动。 我尝试了以下内容: 但是如果玩家碰到了墙,他不会滑动...他只是停下来了。(我对W,A,S,D也是分开做的。) 只有当我将玩家位置设置回他正在触摸的墙壁位置时,它才有效。如下: 但是它不起作用,因为对于与另一面墙相连的墙,玩家会接触更多的边,玩家会跳到角落...所以它只适用于一面墙... 我的问题是:如何以另一种方式使玩家与墙

    • 但是这个示例将敲击位置作为源位置和目标位置。但是我需要给出lat/lang值&需要计算这两个位置的距离和时间值。我怎么做呢?谢谢。

    • 我偶然发现了这个不错的教程https://github.com/manashmndl/DeadSimpleSpeechRecognizer其中数据是基于由文件夹分隔的样本进行训练的,所有mfcc都是一次计算的。 我正试图以不同的方式实现类似的目标。 基于此:https://librosa.github.io/librosa/generated/librosa.feature.mfcc.html l

    • 我正试图在RoR上创建一个计算时间的应用程序。 当您按下开始按钮时,它会拉Time.now,然后,当您按下停止时,它会再次拉Time.now,然后计算两者之间的时间量。然后它会通过to_i将给定的秒转换为整数,然后将整数秒计算为小时:分钟:秒 然而,我的代码出了点问题,它不停地抛出一个又一个错误。 当前顺序为 nil:NilClass 的“未定义方法 '-'”