对布满灰尘的西洋棋宣告将军_纪中2047_dp

123 篇文章 0 订阅

题目描述


维多利加:这里的确有许多书,但是……
这里没有你。

布洛瓦侯爵想利用维多利加来占卜二战的局势。侯爵只给了她一盘西洋棋和 许多书,便将她关在了王宫的地牢。
西洋棋盘可以看成一个 N*M 的网格。西洋棋可以摆放在任何一个格子里, 而不是网格线的交叉点上。
维多利加将一个棋子放在了左上角的格子上。她试着移动这个棋子,棋子只 会向右或者向下移动。
每个格子有一个权值,维多利加想知道,从左上角到右下角的所有路径中:
1.经过的格子的权值和最大是多少?
2.权值和最大的路径一共有多少条?

输入


第一行两个整数 N,M。
接下来 N 行,每行 M 个整数,表示每个格子的权值。

输出


输出两行,第一行表示最大权值和,第二行表示权值和最大的路径数除以 1e9+7 的余数。

样例输入


3 3
1 1 1
1 2 1
1 1 1

样例输出


6
4

Data Constraint


Ai,j 表示第 i 行第 j 列格子的权值。
30%的数据保证,N≤5,M≤5。
60%的数据保证,N≤100,M≤100。
另有 20%的数据保证,对于任意的 i 和 j,Ai,j = 1。
100%的数据保证,N≤2000,M≤2000,|Ai,j|≤10^9。

Analysis


看到维多利加就忍不住出戏了:)

显而易见的dp
f[i][j] 表示到i行j列的最大权值和, g[i][j] 表示到i行j列权值和最大的路径数
DP转移即可,时间复杂度O(NM)
然而第一维可以滚所以空间复杂度O(M)
C++党的胜利

Code


#include <stdio.h>
using namespace std;
long long f[2001],g[2001];
int main()
{
    freopen("chess.in","r",stdin);
    freopen("chess.out","w",stdout);
    int n,m,a;
    scanf("%d%d",&n,&m);
    for (int i=0;i<=m;i++)
        f[i]=-2147483647;
    g[1]=1;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {
            scanf("%d",&a);
            if (i==1&&j==1)
                f[j]=a;
            else
            {
                if (f[j]>f[j-1])
                    f[j]+=a;
                else
                    if (f[j]<f[j-1])
                    {
                        f[j]=f[j-1]+a;
                        g[j]=g[j-1];
                    }
                    else
                    {
                        f[j]=f[j-1]+a;
                        g[j]=(g[j]+g[j-1])%1000000007;
                    }
            }
        }
    }
    printf("%lld\n",f[m]);
    printf("%lld\n",g[m]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值