poj1050最大字段和及其衍生

来源:互联网 发布:czur scanner软件 编辑:程序博客网 时间:2024/06/06 01:24

每天做poj都会感觉到自己的收获,今天做的是poj1050,以前没接触这些算法类的东西,也就在数据结构课上水过两把,所以每天接触到这些新的东西觉得挺有意思,也确实感觉自己收获了不少。

poj1050是一个字段和的题,什么是字段和以及他的具体实现我是在这篇博客上学到的,点击打开链接

对照着他的思路,我自己用Java实现了一下加深理解。字段和简单地说就是给你一行数字,有正有负,我们要做的就是,计算下标i到下标J之间的数字(这之间是连续的下标),是这些数字的和是最大的,我们需要求的就是这个最大值。

根据上面博客的链接,对于字段和的实现大约有三种方法。

1、穷举法

顾名思义,就是依次遍历第一个下标到最后一个下标,最直接的思路是设置三重循环,最外层的大循环是起始坐标的位置,第二层循环是再确定起始坐标的基础上,确定的终止坐标的位置,第三重循环就是变量i在起始坐标和终止坐标之间取值,设置一个max和temp,把每一个变量指定的坐标对应的元素加到temp上,再和max比较大小,如果比max大的话就把值赋给max,此时如果需要记录起始坐标和终点坐标,就要额外设定两个变量用来记录最大值时对应的i和J。

对于上面的这种方法,细想一下的话我们会发现有些步骤是重复的,其实只用两重循环就能做到。已知起始位置,终止位置每向后移一次,就把那个位置对应的元素加到temp上,再和max比较,这样就可以减少时间复杂度。

2、分治法

看完原博客的这个方法之后,理解倒是挺好理解,就是要分情况进行实现,而且对于起始位置和终点位置在不同的半边的那种情况处理起来比较麻烦,我以后应该不会优先考虑这个算法。

3、动态规划法(dp)

又见动态规划,动态规划的思想放在这个题目里面,怎么说呢,因为实现的步骤过于简单,主要是想想清楚这之间的逻辑关系,也就是说为什么这样可以达到目的,还是两个用来记录和的变量max和temp,temp还是记录临时和的变量。当变量i加1指向下一个元素a[i]的时候,判断temp是不是>0,大于0,说明是有必要和a[i]进行相加的,因为如果temp<0的话,无论a[i]的值是正或者负,如果temp和a[i]相加都必然会使和比a[i]要小,因此,当temp<0时,我们将a[i]的值赋给temp作为新的temp值。而在temp>0时,如果a[i]>0,则会使新的temp更大,与max比较如果大于max则对max重新赋值,若否则不作处理,同样,就算a[i]是小于0,就更不会对max的值有影响。这样我们就可以找到这个字段里的最大的数字和。

放在1050这道题里,就算是一个二维的字段求和,只需要在一维的基础上,遍历每一行,将其与下面的一行,两行.....直到最后一行加到一起,组成了一个新的一维字段,所以我们实际是对这个新的字段进行处理。

代码详情如下:

package cn.itcast_test;import java.util.Scanner;public class Max{public static void main(String args[]){Scanner scan=new Scanner(System.in);int n=scan.nextInt();int [][]arr=new int[n][n];for(int i=0;i<n;i++){for(int j=0;j<n;j++){arr[i][j]=scan.nextInt();}}int max=-1000;//挨个计算每一行的最大值for(int i=0;i<n;i++){int temp=0;for(int j=0;j<n;j++){if(temp>0){temp+=arr[i][j];if(temp>max){    max=temp;    }}else{temp=arr[i][j];}}}//依次将每一行与下面的一行、两行、、、、和所有行慢慢累加到一起,算上一行之后进行最大值查找for(int i=0;i<n-1;i++){for(int j=i+1;j<n;j++){int temp=0;for(int k=0;k<n;k++){arr[i][k]+=arr[j][k];if(temp>0){temp+=arr[i][k];if(temp>max){    max=temp;    }}else{temp=arr[i][k];}}}}System.out.println(max);}}


原创粉丝点击