这是一道相对比较基础的DP,但是题目有点说的不清楚,就是yifenfei到魔王lemon的时候魔王lemon的那个数字要不要加上??加上的话如果是正数,那么就有点说不过去,但是从他的答案上看还是需要加上的。那么这样一来就是比较清楚的,这个是类似三角DP的只是加了点条件,原文中是这么说的如果当前格子是(x,y),下一步可以是(x+1,y),(x,y+1)或者(x,y*k) 其中k>1。我想不用我解释你们也是可以明白的,那么这道题就是采用了三角DP的方法直接从后面往前面递推,当然这里常见的有两种方法可以用:
一个就是谈论边上的格子,因为他们的下面或者是右面没有东西。
第二种思维是我们人为地设置出来,比如说题中的3行8列,我们设置4行9列,只要保证增加的不会被使用上,只是满足一下递推的形式即可。那么想不参加选,那就必须让你人为增加的非常小比如--1000000,这个自己酢情考虑。
剩下就是那个增加的条件(x,y*k) ,这样我们还是只比较后面和下面的大小(因为前面条件是只能往下走),在设置一次用来比较后面的走的地方的大小,最后两者取大的即可。
for(i=n;i>0;i--)
{
for(j=m;j>0;j--)
{ Max=-1000000;
a[n][m]=k;
for(p=2;p*j<=m;p++)
{
if(a[i][p*j]>Max)
Max=a[i][p*j]; //这里就是求得可以往后走的所有的最大的(除了后面一步)
//cout<<"hao"<<endl;
}
MAX=max(a[i][j+1],a[i+1][j]); //这里还是下面和后面一位的比较
a[i][j]+=max(Max,MAX); //这里就是求得前面所有的大小之中最大的那个。
}
最后是可以AC的代码:
#include<iostream>
using namespace std;
#include<cstdlib>
int a[25][1005];
int max(int m,int n)
{
return n>m?n:m;
}
int main()
{
int i,j,k;
int p;
int c;
int m,n;
cin>>c;
int Max;
int MAX;
while(c--)
{
MAX=0;
Max=-1000000;
cin>>n>>m;
for(i=0;i<23;i++)
for(j=0;j<1003;j++)
a[i][j]=-1000000;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
cin>>a[i][j];
k=a[n][m];
for(i=n;i>0;i--)
{
for(j=m;j>0;j--)
{ Max=-1000000;
a[n][m]=k;
for(p=2;p*j<=m;p++)
{
if(a[i][p*j]>Max)
Max=a[i][p*j];
//cout<<"hao"<<endl;
}
MAX=max(a[i][j+1],a[i+1][j]);
a[i][j]+=max(Max,MAX);
}
}
cout<<a[1][1]<<endl;
}
return 0;
}
最后把各位总结的数据综合一下:
1 2 -99 10 2 1 -99 -1 2 4 9 -10 -10 4 5 -10 -10 -10 2 4 -9 -10 -10 -4 -5 -10 -10 -10答案分别是:-98 -100 4 -23