PKU OJ 1050 DP(To the max)

http://acm.pku.edu.cn/JudgeOnline/problem?id=1050
第一眼看这个题觉得是动态规划,心里一下子就有点胆怯了,因为不熟悉动态规划的使用,但看了Disscuss后就受到启发,有了想法,尽管估计到可能会超时,但还是试了一下,想验证自己的结果是否正确,找了测试实例全过,交上后果然超时,晕!没法了!
超时算法:很容易理解,就是枚举
#include<stdio.h>
#define N 102
int a[N][N],b[N][N];
int main()
{
 int n,i,j,k,m,z1,z2,max;
 while(scanf("%d",&n)!=EOF)
 {
  for(i=0;i<n;i++)
   for(j=0;j<n;j++)
    scanf("%d",&a[i][j]);
  for(i=0;i<n;i++)
   for(j=0;j<n;j++)
   {
    max=a[i][j];
    for(k=i;k<n;k++)
     for(m=j;m<n;m++)
     {
      b[i][j]=0;
      for(z1=i;z1<=k;z1++)
       for(z2=j;z2<=m;z2++)
        b[i][j]+=a[z1][z2];
      if(b[i][j]>max)
       max=b[i][j];
     }
    b[i][j]=max;
   }
  max=b[0][0];
  for(i=0;i<n;i++)
   for(j=0;j<n;j++)
    if(b[i][j]>max)
     max=b[i][j];
    printf("%d\n",max);
 }
 return 0;
}
再次看了牛人代码后,明白了其思路,知道了如何简化程序,以下为AC代码:
#include<stdio.h>
#define N 102
int a[N][N],b[N];
int main()
{
 int n,i,j,k,x1,x2,max,sum;
 while(scanf("%d",&n)!=EOF)
 {
  for(i=0;i<n;i++)
   for(j=0;j<n;j++)
    scanf("%d",&a[i][j]);
  max=a[0][0];
  for(x1=0;x1<n;x1++)
   for(x2=x1;x2<n;x2++) //遍历:在第X1行和X2行之间的所有矩阵
   {
    sum=0;
    for(j=0;j<n;j++)  //对矩阵每一列求和存入数组b[]
    {   
     b[j]=0;
     for(i=x1;i<=x2;i++)
      b[j]+=a[i][j];     
    }    
    for(k=0;k<n;k++)  //找出最大值矩阵
    {
     if(sum>=0) sum+=b[k];
     else   sum=b[k];
     if(sum>max)  max=sum;
    }
   } 
  printf("%d\n",max);
 }
 return 0;
}

按这种思路可以减少for循环次数,节省时间,因此AC了!不过看懂这个思路,真的花了我不少时间,终于明白了,真的好考验人的理解能力啊!但应该还不是最简单的算法,以后有幸得到了再作修改吧!
解法3:DP思想:
#include<stdio.h>
#define N 102
int a[N][N];
int main()
{
    int n,i,j,k,m,sum,max;
    scanf("%d",&n);
    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
            scanf("%d",&a[i][j]);
    max=-128;
    for(i=0;i<n;i++)
        for(j=i;j<n;j++)
        {
            sum=0;
            for(k=0;k<n;k++)
            {
                for(m=i;m<=j;m++)
                    sum+=a[m][k];
                if(sum>max)
                    max=sum;
                if(sum<0)
                    sum=0;
            }
        }
    printf("%d\n",max);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值