杭电2571

这是一道相对比较基础的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 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值