繁体   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