简单的方格取数模板,不过多加了可以跳到同行的倍数列。
和方格取数类似,用dp[i][j]表示i行j列取得数字和的最大值。
则dp[i][j]只和它的前一步有关,即dp[i-1][j]或者dp[i][j-1]或者dp[i][j/l](如果j能被l整除且l>1)。
状态转移方程:dp[i][j]=max{dp[i-1][j],dp[i][j-1],dp[i][j/l]}其中j%l==0;
需要注意的是这题初始化dp数组要开一个非常小的数,因为给的数据可能有到一个格子后得分为一个绝对值很大的负数,初始化为-20*1000*100即可。
代码:
#include<stdio.h>
#include<string.h>
#include<limits.h>
int max2(int a,int b)
{
return a>=b?a:b;
}
int max3(int a,int b,int c)
{
return max2(a,b)>=c?max2(a,b):c;
}
int main()
{
int c,m,n;
scanf("%d",&c);
while(c--)
{
int k[25][1005];
memset(k,0,sizeof(k));
int dp[22][1005];
memset(dp,-2000000,sizeof(dp));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&k[i][j]);
}
}
dp[1][1]=k[1][1];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(i==1&&j==1)continue;
else
{int t,m=INT_MIN;
for(int l=2;l<=j;l++)
{
if(j%l==0)
{
t=max3(dp[i-1][j],dp[i][j-1],dp[i][j/l])+k[i][j];
if(m<t)m=t;
}
}
t=max2(dp[i-1][j],dp[i][j-1])+k[i][j];
if(m<t)m=t;
dp[i][j]=m;}
}
}
printf("%d\n",dp[n][m]);
}
}