练习了几个星期的动态规划,结果在POJ上随便找些题目还是不会做。。
看见这种题第一反应就是构造dp[i][j]以(i,j)结尾的矩阵的状态转移方程,然后找不出来陷入误区。
最大子矩阵问题:
问题描述:(具体见http://acm.pku.edu.cn/JudgeOnline /showproblem?problem_id=1050)
给定一个n*n(0<n<=100)的矩阵,请找到此矩阵的一个子矩阵,并且此子矩阵的各个元素的和最大,输出这个最大的值。
Example:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其中左上角的子矩阵:
9 2
-4 1
-1 8
此子矩阵的值为9+2+(-4)+1+(-1)+8=15。
分析:
本题虽然为矩阵,但思想就是将它转化为一列数,然后再求最大子序列和。但如何转化?
7 -8 9
-4 5 6
1 2 -3
主要是将同一列中的若干数合并。比如,从第一行开始,到第2行结束,每一列的和组成的序列为:
3 -3 15
然后从上到下枚举这样的序列,对每个序列进行一次求连续最大子序列和的DP即可。
JAVA AC代码:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package myjava;
import java.util.Scanner;
/**
*
* @author Administrator
*/
public class Main1050 {
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int num=scan.nextInt();
int[][]a=new int[num+1][num+1];
for(int i=1;i<=num;i++){
for(int j=1;j<=num;j++){
a[i][j]=scan.nextInt();
}
}
int max=Integer.MIN_VALUE/2;
int[]dp=new int[num+1];
for(int i=1;i<=num;i++){
for(int j=i;j<=num;j++){ //第i行到第j行
int[]temp=new int[num+1];
for(int k=1;k<=num;k++){ //线性序列DP
for(int m=i;m<=j;m++){ //累加
temp[k]+=a[m][k];
}
int x=temp[k]+temp[k-1]; //如果加上这一项
if(x>temp[k]){ //如果temp[k-1]>0
temp[k]=x;
}
if(temp[k]>max) max=temp[k];
}
}
}
System.out.println(max);
}
}