FJUT 1735 开宝箱

FJUT 1735

开宝箱
你确定我是来开宝箱不是来比赛的吗??艾玛,这是哪,天啊,伦家竟然穿越了。
摆在眼前的是1个n*m(0< n<=100&&0< m<=100)的宝箱矩阵,而你就在这个矩阵的左上角也就是入口处。冲啊,开宝箱去,然而脚不听话啊,你的脚失去了向左走与向上走(方向是相对于整个地图,换句话说不是通过你脸的朝向来决定方向,你只能↓和→)的能力。(你:这设定真奇怪啊 。WGX大神:让你四处走还不把我的宝箱全开了)。
不管了开宝箱要紧。假设每个宝箱有一个数字V,如果是正数那么你获得V个金币,如果是负数,哈哈,不好意思,扣去相应个金币。(哭晕在厕所)。
那么问题来了:
如果你在已知宝箱的奖励的情况下,请选择一条路线,这条路线能让你获得最多的金币,当然所有走过的宝箱必须打开,不能说因为是负数你就选择不去打开它,并且出口(左上)和入口(右下)的那两个宝箱是必经点,也必须打开。
你的任务只是求出该路线获得的金币值就行。如下图,我们只要输出19就行。

Input
第一行输入一个正整数T代表有T组数据,接下来有T组数据
对于每组数据,第一行输入两个正整数n 和m(n为行数m为列数)接下来是n行数据,每行数据有m个V,且V为整型,分别对应每个宝箱的获奖情况(-200<=V<=200)。
Output
对于每组数据输出一个整数,代表所能获得的最大金币值。
SampleInput
2
4 4
1 2 -9 8
-5 5 7 3
10 1 1 2
6 5 8 -6
3 5
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
SampleOutput
19
7

从左上角开始,到右下角出去,求经过路线的和的最大值。。。又是一道dp题。。。找到初始状态,状态转移,还有最后的结果位置,弄清楚这些,分分钟就可以AC了。
首先找三个步骤中最关键的一步状态转移:每一次只能向下或者向右,那么就有了下面的状态转移方程:
dp[i] [j]= max( dp[i-1] [j], dp[i] [j-1])+a[i] [j];
就是根据移动 反推即可。当前的最优解就是上一步的最优解加上这一步的数据,所有子问题达到最优就能实现整体最优。。
当然这里注意下三点
1、让数组的i j 都从1开始输入,因为有个dp[i-1] [j-1] 防止下标小于0的情况
2、每一格的范围-200到200 所以让dp 【i】【j】初始化为小于-200的数值.
3、 i=j=1的时候特判一下dp的值

代码参考如下:

#include<stdio.h>
int max(int a,int b)
{ 
   return a>b?a:b;
}
int b[101][101];
int f[101][101];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m,i,j,k,kk;
        scanf("%d%d",&n,&m);
        for(i=0;i<=n+1;i++)
        {
            for(j=0;j<=m+1;j++)
                f[i][j]=-201;
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
                scanf("%d",&b[i][j]);
        }
           for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                if(i==1 && j==1)
                    f[1][1]=b[1][1];
                else
                 f[i][j]=max(f[i-1][j],f[i][j-1])+b[i][j];
            }
        }
        printf("%d\n",f[n][m]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43563669/article/details/86517376