杭电2571(DP)。

http://acm.hdu.edu.cn/showproblem.php?pid=2571

题意:求出从从(1,1)走到(n,m)的最大值!并且必须按要求走!!

另外一种就是用搜索做!求出最大的值!

状态方程:sum[i][j]=max{sum[i-1][j],sum[i][k]}+v[i][j];其中1<=k<=j-1,且k是j的因子。

具体见代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int dp[25][1005];
int val[25][1005];
int main()
{
    int i,j,k,t,n,m;
     scanf("%d",&t);
     while(t--)
     {
         scanf("%d%d",&n,&m);
         for(i=1;i<=n;i++)
         {
             for(j=1;j<=m;j++)
             {
               scanf("%d",&val[i][j]);
               dp[i][j]=-20000;//注意初始化!!
             }
         }
        // memset(dp,-20000,sizeof(dp));
         dp[1][1]=val[1][1];
         for(i=1;i<=n;i++)
         {
             for(j=1;j<=m;j++)
             {
               if(i+1<=n)
                dp[i+1][j]=max(dp[i+1][j],dp[i][j]+val[i+1][j]);//求出向右走一步的最大值!
               if(j!=1)
               {
                   if(j+1<=m)
                    dp[i][j+1]=max(dp[i][j+1],dp[i][j]+val[i][j+1]);//求出向下走一步的最大值!
               }
               k=2;//以下为求出走到该行的列数是当前所在列数倍数的格子的最大值!!
               while(k*j<=m)//这里要注意while与if的用法(if 只要条件为真就执行(且只执行一次,即执行到{}内最后一行就不执行了。
//while 只要条件为真就一直循环执,直到条件为假,即执行到{}内最后一行还会返回(fahr<=upper)做判断,如果条件还是真的则再执行{}里的内容
               {
                 dp[i][j*k]=max(dp[i][j]+val[i][j*k],dp[i][j*k]);
                 k++;
               }
             }
         }
         printf("%d\n",dp[n][m]);
     }
     return 0;
}


猜你喜欢

转载自blog.csdn.net/u010200793/article/details/16330757