深度优先

这个家伙好懒,除了文章什么都没留下

0%

时间限制:1.0s 内存限制:256.0MB
提交此题
问题描述
给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。

其中,A的子矩阵指在A中行和列均连续的一块。
输入格式
输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
接下来n行,每行m个整数,表示矩阵A。
输出格式
输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。
样例输入
3 3
-1 -4 3
3 4 -1
-5 -2 8
样例输出
10
样例说明
取最后一列,和为10。
数据规模和约定
对于50%的数据,1<=n, m<=50;

对于100%的数据,1<=n, m<=500,A中每个元素的绝对值不超过5000。

几乎同样的代码C++能过100%的数据,而java只能过50%的数据,郁闷啊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import java.util.Scanner;
public class 最大子阵 {

static int ans=Integer.MIN_VALUE;
public static void main(String[] args) {

Scanner sc=new Scanner(System.in);

//while(sc.hasNext()){
int n=sc.nextInt();
int m=sc.nextInt();
int[][] data=new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
data[i][j]=sc.nextInt();
}
}
int[] dp=new int[m+1];
//统计几行的
for (int h = 1; h <= n; h++) {
//从哪一行开始算起
for (int i = 0; i < n; i++) {
int[] arr=new int[m+1];
for (int j = i; j < i+h&&j<n; j++) {

for (int p = 1; p < arr.length; p++) {
arr[p]+=data[j][p-1];
}
dp[1]=arr[1];
if(dp[1]>ans){
ans=dp[1];
}
for (int w = 2; w < arr.length; w++) {
if(dp[w-1]<0)
dp[w]=arr[w];
else
dp[w]=dp[w-1]+arr[w];
if(dp[w]>ans)
ans=dp[w];
}
}
//getSum(arr);
}
}
//}
System.out.println(ans);
sc.close();
}

private static void getSum(int[] arr) {
int sum=0,max=Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
int num=arr[i];

if(sum>0)
sum += num;
else
sum = num;

if(sum>max)
max = sum;
}
if(max>ans)
ans=max;
}
}

Description
在X森林里,上帝创建了生命之树。

他给每棵树的每个节点(叶子也称为一个节点)上,都标了一个整数,代表这个点的和谐值。
上帝要在这棵树内选出一个非空节点集S,使得对于S中的任意两个点a,b,都存在一个点列 {a, v1, v2, …, vk, b} 使得这个点列中的每个点都是S里面的元素,且序列中相邻两个点间有一条边相连。

在这个前提下,上帝要使得S中的点所对应的整数的和尽量大。
这个最大的和就是上帝给生命之树的评分。

经过atm的努力,他已经知道了上帝给每棵树上每个节点上的整数。但是由于 atm 不擅长计算,他不知道怎样有效的求评分。他需要你为他写一个程序来计算一棵树的分数。

「输入格式」
第一行一个整数 n 表示这棵树有 n 个节点。
第二行 n 个整数,依次表示每个节点的评分。
接下来 n-1 行,每行 2 个整数 u, v,表示存在一条 u 到 v 的边。由于这是一棵树,所以是不存在环的。

「输出格式」
输出一行一个数,表示上帝给这棵树的分数。

「样例输入」
5
1 -2 -3 4 5
4 2
3 1
1 2
2 5

「样例输出」
8

Input
第一行一个整数 n 表示这棵树有 n 个节点。
第二行 n 个整数,依次表示每个节点的评分。
接下来 n-1 行,每行 2 个整数 u, v,表示存在一条 u 到 v 的边。由于这是一棵树,所以是不存在环的。
Output
输出一行一个数,表示上帝给这棵树的分数。
Sample Input
5
1 -2 -3 4 5
4 2
3 1
1 2
2 5
Sample Output

8

这题瞎搜,居然被我水过去了,严重怀疑学校的测试数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package 省赛2015;

import java.util.Scanner;

public class T9 {

static boolean[][] data;
static boolean[][] data1;
static int[] fenzhi;
static int max;
static int n;
static boolean[] vis;

public static void main(String[] args) {

Scanner sc=new Scanner(System.in);
n=sc.nextInt();

fenzhi=new int[n+1];
for (int i = 1; i <= n; i++) {
fenzhi[i]=sc.nextInt();
}

data=new boolean[n+1][n+1];
data1=new boolean[n+1][n+1];
vis=new boolean[n+1];

for (int i = 1; i < n; i++) {
int a=sc.nextInt();
int b=sc.nextInt();

data1[a][b]=data1[b][a]=data[a][b]=data[b][a]=true;

}

//
for (int i = 1; i < n; i++) {
for (int j = i+1; j <= n; j++) {
vis=new boolean[n+1];
vis[i]=true;
dfs(i,j,fenzhi[i]);

for (int a = 0; a <= n; a++) {
for (int b = 0; b <= n; b++) {
data[a][b]=data1[a][b];
}
}
}
}
System.out.println(max);
}
private static void dfs(int begin,int end,int fen) {

if(data[begin][end]){

for (int i = 1; i <= n; i++) {
if(vis[i]||i==end)continue;
if(data[begin][i]){
if(fenzhi[i]>0)
fen+=fenzhi[i];
}
}

for (int i = 1; i <= n; i++) {
if(vis[i]||i==begin)continue;
if(data[end][i]){
if(fenzhi[i]>0)
fen+=fenzhi[i];
}
}
fen+=fenzhi[end];
if(fen>max){
max=fen;
}
return;
}

for (int i = 1; i <= n; i++) {
if(vis[i])continue;

if(data[end][i]){
data[end][i]=false;
vis[i]=true;
fen+=fenzhi[i];

dfs(end,i,fen);

data[end][i]=true;
vis[i]=false;
fen-=fenzhi[i];
}
}
}
}

又是同学提问的一题,帮他解决了。

将从1到n这n个整数围成一个圆环,若其中任意2个相邻的数字相加,

结果均为素数,那么这个环就成为素数环。

n=20时,下面的序列就是一个素数环:
1 2 3 4 7 6 5 8 9 10 13 16 15 14 17 20 11 12 19 18

任意输入n,求满足n的所有素数环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class 素数圈 {

static int[][] data;
static boolean[] vis;
static long t;

public static void main(String[] args) {

int n=18;
data=new int[n+1][n+1];
int[] arr=new int[n];
for (int i = 1; i <= n; i++) {
int t=0;
for (int j = 1; j <= n; j++) {
if(getSuNum(i+j)){
data[i][t]=j;
t++;
}
}
}
vis=new boolean[n+1];
for (int i = 0; i <= n; i++) {
vis[i]=false;
}

arr[0]=1;
dfs(1,data,arr,1);
System.out.println(t);
}
private static void dfs(int i, int[][] data,int[] arr,int k) {

if(k>arr.length-1){
// for (int j = 0; j < arr.length; j++) {
// System.out.print(arr[j]+" ");
// }
// System.out.println();
t++;
return;
}

for (int j = 1; j < data.length && data[i][j]!=0; j++) {
if(vis[data[i][j]]==true) continue;

vis[data[i][j]]=true;
arr[k]=data[i][j];
dfs(data[i][j],data,arr,k+1);
vis[data[i][j]]=false;
}

}
private static boolean getSuNum(int num) {

for (int i = 2; i < num; i++) {
if(num%i==0)
return false;
}
return true;
}
}