POJ 1050 To the Max

来源:互联网 发布:淘宝怎么卡地区 编辑:程序博客网 时间:2024/05/21 06:33

POJ 1050 To the Max


算法解析:这道题好像最小的时间复杂度是O(N^4)(那些说O(N^3)都是数学没学好没整清楚复杂度定义的),我的算法复杂度是O(N^5),当时为了比较两个算法的复杂度我就直接使用了我的算法,后来发现过倒是能过掉,但是时间花费大概多了20倍(O(N^4)是30多ms,O(N^5)是700多ms)。

O(N^5)的算法很好理解,遍历矩阵中每个点(i,j),从这个点出发再构造左上点为(i,j)右下点为(x,y)的子矩阵,遍历这些矩阵寻找点(i,j)为左上点的子矩阵中和最大的子矩阵,最后选出所有点中最大的子矩阵和值。

O(N^4)的算法最大的优势在于将二维矩阵压缩成一维来处理(这是二维矩阵经常使用的一个处理方法!),具体的分析请参照参考一和参考二,参考一有图比较直观,参考二则把算法中最重要的动态规划思想加以详细介绍,唯一的遗憾是没写清楚

dp[i] = max{a[i], dp[i-1] + a[i]}

解释一下方程:

如果dp[i-1] > 0,则 dp[i] = dp[i-1] + a[i]
如果dp[i-1] < 0,则 dp[i] = a[i]

是需要变形dp+a[i]-a[i] ? dp+a[i] : a[i]得到的


算法实现:没啥需要注意的,就是哪几个循环的意义需要搞清楚,上下界别乱写。


#include<iostream>using namespace std;//#include <fstream>int m[100][100];int r[100][100];int main(){//ifstream infile("test.txt");//ofstream outfile("result.txt");//输入int n;cin>>n;//infile>>n;for (int i=0; i!=n; i++){for (int j=0; j!=n; j++){scanf("%d",&m[i][j]);//infile>>m[i][j];r[i][j]=m[i][j];}}//计算,以每个点为矩阵左上起点for (int i=0; i!=n; i++){for (int j=0; j!=n; j++){//计算矩阵右下终点为(x,y)的sum值for (int x=i; x!=n; x++){int sum=0;for (int y=j; y!=n; y++){for (int k=i; k<=x; k++){sum+=m[k][y];}if (sum>r[i][j]){r[i][j]=sum;}}}}}int max=-128;for (int i=0; i!=n; i++){for (int j=0; j!=n; j++){if (r[i][j]>max){max=r[i][j];}}}printf("%d",max);//cout<<max<<endl;//outfile<<max<<endl;//infile.close();//outfile.close();return 0;}

其他:注意动态规划问题都需要给定一个起点或者终点(两头不定的则需要遍历起点(终点)进行动态规划)

原创粉丝点击