`

POJ1050-To the Max-DP

 
阅读更多
参见《编程之美》2.14, 2.15 子数组和最大值(一维&二维)

转:POJ 2479/POJ 2593的拓展,从一维数组变成了二维矩阵,不过我们可以把情况模拟成一维的情况,在DP的基础上需要加上枚举。
题目要求求出给定的一个矩阵的和最大的子矩阵。

我们可以枚举第a行到第c行的情况(假设已经确定矩阵已经确定为最上面为第a行,最下面为第c行),那么只需要确定列的范围即可。我们可以把每一列都求和,这样会得到单独的一行,就可以直接求这一行的最大子段和即可。


 

代码:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

#define INF 1<<27
#define MAX_SIZE 101

int res=-INF;
int n;
int map[MAX_SIZE][MAX_SIZE];

int max(int a,int b){
	return (a)>(b)?a:b;
}

void find_max(int top,int bottem){
	//1. 退化为一维数组
	int arr[MAX_SIZE];
	memset(arr,0,sizeof(arr));

	int i,j;
	for(i=0;i<n;i++){
		for(j=top;j<=bottem;j++){
			arr[i]+=map[j][i];
		}
	}

	//2. 求一位数组arr[0, ... , n-1]的和最大子数组的和

	//*下面这种初始化方法使得如果全部为负数的话,最大值输出最大负数,而非0
	int start[MAX_SIZE],all[MAX_SIZE];
	all[n-1]=start[n-1]=arr[n-1];

	for(i=n-2;i>=0;i--){
		start[i]=max(arr[i],arr[i]+start[i+1]);
		all[i]=max(start[i],all[i+1]);
	}

	if(all[0]>res) res=all[0];
}

void solve(){
	//枚举最上面一行和最下面一行
	int i,j;
	for(i=0;i<n;i++){
		for(j=i;j<n;j++){
			find_max(i,j);//DP:指定上下范围后,将矩形退化为一个数组,即求解数组的"和最大子数组"
		}
	}
}

int main(){
	scanf("%d",&n);
	int i,j;
	for(i=0;i<n;i++){
		for(j=0;j<n;j++){
			scanf("%d",&map[i][j]);
		}
	}
	solve();
	printf("%d",res);
	system("pause");

	return 0;
}
 

 

  • 大小: 17.8 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics