【发布时间】:2014-04-16 15:06:38
【问题描述】:
我遇到了这个problem。
它要求计算特定长度的锁定模式可以在 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;
}
【问题讨论】:
标签: c++ algorithm combinations permutation