簡體   English   中英

4乘3鎖模式

[英]4 by 3 lock pattern

我遇到了這個問題

要求計算特定長度的鎖定模式可以在4x3網格中進行並遵循規則的方式的數量。 可能有一些點不得包含在路徑中

有效模式具有以下屬性:

  • 可以使用它第一次觸摸的點序列(以與繪制圖案相同的順序)來表示圖案,從(1,1)到(2,2)的圖案與圖案不同從(2,2)到(1,1)。

  • 對於模式表示中的每兩個連續點A和B,如果連接A和B的線段通過其他一些點,則這些點也必須在序列中並且在A和B之前,否則模式將無效。 例如,以(3,1)然后(1,3)開頭的模式表示是無效的,因為段經過(2,2),它沒有出現在(3,1)之前的模式表示中,並且正確該模式的表示為(3,1)(2,2)(1,3)。 但模式(2,2)(3,2)(3,1)(1,3)是有效的,因為(2,2)出現在(3,1)之前。

  • 在模式表示中,我們不會多次提及相同的點,即使模式將通過另一個有效的段再次觸及此點,並且模式中的每個段必須從一個點到另一個點,該模式沒有之前觸摸它可能會經過一些已經出現在模式中的點。

  • 模式的長度是模式表示中每兩個連續點之間的曼哈頓距離的總和。 兩點(X1,Y1)和(X2,Y2)之間的曼哈頓距離是| X1-X2 | + | Y1 - Y2 | (其中| X |表示X的絕對值)。

  • 模式必須至少觸及兩點

我的方法是蠻力,循環點,從點開始並使用遞歸遞減長度直到達到零長度然后將組合數加1。

有沒有辦法在數學方程中計算它或者有更好的算法?

更新:這是我所做的,它給出了一些錯誤的答案! 我認為問題在於isOk功能! notAllowed是不允許的點的全局位掩碼。

bool isOk(int i, int j, int di,int dj, ll visited){
    int mini = (i<di)?i:di;
    int minj = (j<dj)?j:dj;

    if(abs(i-di) == 2 && abs(j-dj) == 2 && !getbit(visited, mini+1, minj+1) )
        return false;
    if(di == i && abs(j - dj) == 2 && !getbit(visited, i,minj+1) )
        return false;
    if(di == i && abs(j-dj) == 3 && (!getbit(visited, i,1) || !getbit(visited, i,2)) )
        return false;
    if(dj == j && abs(i - di) == 2 && !getbit(visited, 1,j) )
        return false;

    return true;
}

int f(int i, int j, ll visited, int l){
    if(l > L) return 0;
    short& res = dp[i][j][visited][l];
    if(res != -1) return res;
    res = 0;
    if(l == L) return ++res;

    for(int di=0 ; di<gN ; ++di){
        for(int dj=0 ; dj<gM ; ++dj){
            if( getbit(notAllowed, di, dj) || getbit(visited, di, dj) || !isOk(i,j, di,dj,  visited) )
                continue;
            res += f(di, dj, setbit(visited, di, dj), l+dist(i,j , di,dj));
        }
    }
    return res;
}

我對另一個問題的回答也可以適應這個問題。

f(i,j,visited,k)完成部分模式的方式數,當我們當前在節點(i,j)時,已經訪問了訪問集中的頂點並且到目前為止已經走了一個路徑長度k個。 我們可以將訪問表示為位掩碼。

我們可以通過嘗試所有可能的下一步移動來遞歸計算f(i,j,visited,k)並應用DP來重用子問題解決方案:

f(i,j,visited,L)= 1

如果k> L,則f(i,j,visited,k)= 0

f(i,j,visited,k)= sum(可能的移動(i',j'):f(i',j',訪問UNION {(i',j')},k + dis((i, j),(i',j')))

可能的移動是那些跨越多個被訪問頂點然后以單向(並且不被禁止)結束的移動。

如果D是禁止頂點的集合,問題的答案是

sum((i,j)不在D:f(i,j,{(i,j)},L))。

運行時類似於O(X ^ 2 * Y ^ 2 * 2 ^(X * Y)*最大可能長度)。 我想最大可能的長度實際上遠低於1000

更新:我實施了這個解決方案,它被接受了。 我用以下方式列舉了可能的移動:假設我們在點(i,j)並且已經訪問了所訪問的頂點集。 枚舉所有不同的互質對(dx,dy)0 <= dx <X和0 <= dy <Y。然后找到最小的k,其中P_k =(i + k dx,j + k dy)仍然是有效網格點並且P_k沒有訪問過 如果不禁止P_k,則為有效移動。

最大可能路徑長度為39。

我正在使用大小為3 * 4 * 2 ^ 12 * 40的DP陣列來存儲子問題結果。

可以使用組合的一些屬性來優化強力方法:

  1. 使用鏡像(水平,垂直或兩者),您可以為每個找到的組合生成4種組合(水平或垂直線除外)。 也許你只能考慮從一個象限開始的組合。

  2. 您通常可以通過平移生成相同長度的其他組合(移動組合)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM