Java 用全部素数计算子矩阵
我得到了一个NxN矩阵。如果子矩阵满足以下条件,则认为它是特殊的:Java 用全部素数计算子矩阵,java,algorithm,matrix,dynamic-programming,Java,Algorithm,Matrix,Dynamic Programming,我得到了一个NxN矩阵。如果子矩阵满足以下条件,则认为它是特殊的: 它的形状一定是正方形的 所有数字都必须是素数 我必须计算满足以下条件的给定矩阵的子矩阵的总数 例如,让示例输入为=> 3 3 5 6 8 3 2 3 5 2 样本输出:8 说明: 1x1:有7个素数,每个1x1矩阵包含1个素数 2x2:只有右下角的子矩阵包含所有素数 3x3:没有3x3矩阵满足这些标准 最后的答案是(7+1+0)=8 我最近在一次采访中遇到了这个问题。我可以想出一个暴力解决方案。解决这个问题的最好办法是什么
3
3 5 6
8 3 2
3 5 2
样本输出:8
说明:
- 1x1:有7个素数,每个1x1矩阵包含1个素数
- 2x2:只有右下角的子矩阵包含所有素数
- 3x3:没有3x3矩阵满足这些标准
class TestClass
{
public static boolean isPrime(int n)
{
if(n<2)
return false;
for(int i=2;i<=Math.sqrt(n);i++)
{
if(n%i==0)
return false;
}
return true;
}
public static boolean scan_matrix(boolean a[][], int start_i, int start_j, int n)
{
for(int i=start_i;i<start_i+n;i++)
{
for(int j=start_j;j<start_j+n;j++)
{
if(!a[i][j])
return false;
}
}
return true;
}
public static int count_valid_matrix(boolean a[][], int n, int N)
{
int result = 0;
for(int start_i=0;start_i<=N-n;start_i++)
{
for(int start_j=0;start_j<=N-n;start_j++)
{
if(scan_matrix(a, start_i, start_j, n))
result += 1;
}
}
return result;
}
public static void main(String args[]) throws Exception
{
Scanner s = new Scanner(System.in);
int N = s.nextInt();
boolean a[][] = new boolean[N][N];
int result = 0;
for(int i=0;i<N; i++)
{
for(int j=0;j<N;j++)
{
int num = s.nextInt();
a[i][j] = isPrime(num);
if(a[i][j])
result += 1;
}
}
int n = 2;
while(n<N)
{
result += count_valid_matrix(a, n, N);
n++;
}
System.out.println(result);
}
}
class测试类
{
公共静态布尔iPrime(int n)
{
如果(n这里是一个可能公式的一部分。让是特殊的(I,J,W)
表示矩阵单元m(I,J)
是否是宽度有效平方的右下角W
。然后:
是特别的(I,J,1)->
is_素数(m(I,J));
是特别的(I,J,W)->
(I>=W-1,假设I从0开始
(J>=W-1,假设J从0开始
(I,J,W-1)和
是特殊的(I-1,J,W-1)和
_是特殊的(I,J-1,W-1)和
是特别的(I-1,J-1,W-1))。
Idea
首先,将(你做的)矩阵转换成0/1矩阵,
非素数用0
,素数用1
现在,你有一个1
s的“曲面”。你能在这个曲面上放多少个正方形?
想想看:如果你有一个3*3
平方的1
s从(0,0)
开始,那么你已经
知道方块(1,0)-(2,1)
,(0,1)-(1,2)
和(1,1)-(2,2)
由1
组成,因此您不必再次检查这些方块。
因此,您将查找从(1,0)
、(0,1)
或(1,1)
开始的1
平方,前提是它们大于2*2
。
想象一下,从(1,0)
开始的最大正方形的大小为3*3
,但另外两个正方形的大小为2*2
。
您可以忽略后者(它们不会添加任何新内容),但必须添加新的3*3
square并删除与前一个重叠的曲面
这可以概括如下:
- 将从
(0,0)
开始的最大正方形大小存储在矩阵M
- 设
N
=大小为M[0,0]
- 对于每个
(r,c)
,从左到右,从上到下:
- 从
M
获取从(r-1,c)
,(r,c-1)
或(r-1,c-1)
开始的最大正方形大小,比如说K
- 计算从
(r,c)
开始的最大正方形大小(从K-1开始)
- 如果
M[r,c]
=K-1
,则不执行任何操作
- 如果
M[r,c]
K-1
,则更新N
:N
+=一个正方形大小的子正方形数M[r,c]
-子正方形数
正方形大小的子正方形K-1
诀窍是“计算从(r,c)
(从K-1开始)
)开始的最大正方形大小”将省去大量比较
伪代码(类似Python)
首先,请注意,大小为k
的正方形包含大小为k^2
的正方形1
,(k-1)^2
的正方形
大小2
,…,1
大小的平方k
。这是一个众所周知的总数(我从维基百科获得了结果!):
计算凝视(r,c)
的1
s的最大平方的大小并不困难。我添加了一个从K开始的开始:
def largest_square_size(m, r, c, K):
k = K
while k<n:
# check the border
for l in 0..k:
if m[r+k, c+l] == 0 or m[r+l, c+k] == 0: # consider the left and bottom borders
break while
if m[r+k, c+k] == 0 # don't forget the corner
break while
k += 1
return k
免责声明:我没有测试这一点,可能有边缘的情况,但我认为这是正确的
它显然是次优的,因为某些位置可能会被多次检查,但它应该表现良好。你能展示你的尝试吗?看起来是动态规划算法的一个很好的候选者。2x2矩阵实际上是4个彼此相邻的1x1矩阵,这意味着如果你解决较小矩阵的问题,并保存相关信息,应建立。提示1:每个2x2子矩阵包含四个1x1子矩阵。每个3x3子矩阵包含四个2x2子矩阵。提示2:
def largest_square_size(m, r, c, K):
k = K
while k<n:
# check the border
for l in 0..k:
if m[r+k, c+l] == 0 or m[r+l, c+k] == 0: # consider the left and bottom borders
break while
if m[r+k, c+k] == 0 # don't forget the corner
break while
k += 1
return k
for r in 0..n:
for c in 0..n:
K = max(M[r-1,c-1], M[r-1,c], M[r,c-1]) - 1 # add boundary check, K = 0 if r,c = 0,0
M[r,c] = largest_square_size(m, r, c, K)
if M[r,c] > K:
N += subsquares_count(M[0,0]) - subsquares_count(K)