您的位置:首页 > 其它

NYOJ104——动态规划的运用

2012-11-09 18:14 211 查看
每一道题目,只要你愿意耐心的去发现它的思路,你会发现其中其乐无穷。

题目非常简单,就是求一个子矩阵使得其各项的和最大。

在这里我们先回想一下求一个数组的最大连续字串和,假定一整形数列{a1,a2,a3,...,an},找出连续的非空子串{ax,ax+1,ax+2,...,ax+y},使得该子序列的的和最大。思路:假设F[m]表示以第m个数结尾的最大连续字串和,则F[m]=max{F[m-1],0}+a[m],然后再求出F[m]数组中的最大值即可,代码为:

maxsum=-INT_MAX;
scanf("%d",&m);
for(int i=1;i<=m;++i)
{
scanf("%d",&a[i]);
if(a[i-1]>0) a[i]+=a[i-1];
if(a[i]>maxsum) maxsum=a[i];
}

printf("%d\n",maxsum);


联系本题,即将二维转化为一维,分析如下:

假设最大子矩阵的结果为从第r行到k行、从第i列到j列的子矩阵,如下所示(ari表示a[r][i],假设数组下标从1开始):

  | a11 …… a1i ……a1j ……a1n |

  | a21 …… a2i ……a2j ……a2n |

  |  .     .     .    .    .     .    .   |

  |  .     .     .    .    .     .    .   |

  | ar1 …… ari ……arj ……arn |

  |  .     .     .    .    .     .    .   |

  |  .     .     .    .    .     .    .   |

  | ak1 …… aki ……akj ……akn |

  |  .     .     .    .    .     .    .   |

  | an1 …… ani ……anj ……ann |

那么我们将从第r行到第k行的每一行中相同列的加起来,可以得到一个一维数组如下:

(ar1+……+ak1, ar2+……+ak2, ……,arn+……+akn)

由此我们可以看出最后所求的就是此一维数组的最大子断和问题,到此我们已经将问题转化为上面的已经解决了的问题了。
在此插入代码,仔细分析一下三个for循环,便可发现这道题也是挺easy的
 
#include<stdio.h>
#include<string.h>

const int MAX=102;
int arr[MAX][MAX];
//定义参数max接收最大值
int max;

int row,col;
//得到每一行连续的最大值
void getMax(int a);

int main()
{
//freopen("in.txt","r",stdin);
int n;
scanf("%d",&n);
while(n--)
{
memset(arr,0,sizeof(arr));
scanf("%d%d",&row,&col);
for(int i=1;i<=row;++i)
{
for(int j=1;j<=col;++j)
{
scanf("%d",&arr[i][j]);
}
}

max=arr[1][1];
for(int i=1;i<=row;++i)
{
getMax(i);//获得第i行的最大连续子串和
for(int j=i+1;j<=row;++j)
{
for(int k=1;k<=col;++k)
arr[i][k]+=arr[j][k];
getMax(i);//获得第i行至第j行的最大连续子串和
}
}
printf("%d\n",max);
}
}

void getMax(int a)
{
int temp=0;
for(int i=1;i<=col;++i)
{
if(temp>0)
temp+=arr[a][i];
else
temp=arr[a][i];
if(temp>max)
max=temp;
}
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: