T266691 对布满灰尘的西洋棋宣告将军

觉得写这道()题题解的人挺少的,那我就来发一篇c++的吧

首先题目描述:

布洛瓦侯爵想利用维多利加来占卜二战的局势。侯爵只给了她一盘西洋棋和 许多书,便将她关在了王宫的地牢。 

西洋棋盘可以看成一个 N * M 的网格。西洋棋可以摆放在任何一个格子里, 而不是网格线的交叉点上。 

维多利加将一个棋子放在了左上角的格子上。她试着移动这个棋子,棋子只 会向右或者向下移动。 

每个格子有一个权值,维多利加想知道,从左上角到右下角的所有路径中: 

1. 经过的格子的权值和最大是多少? 
2. 权值和最大的路径一共有多少条?

输入格式

第一行两个整数 N,M。 

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

输出格式

输出两行,

第一行表示最大权值和,

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

样例 #1

样例输入 #1

3 3 
1 1 1 
1 2 1 
1 1 1

样例输出 #1

6
4

提示

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。



一道DP题


大致思路:


 首先定义两个数组 f 和 g 分别表示最大数路径数

 先写两个循环分别表示n层m列,然后里面逐个输入并进行判断,先输入当前值
 
 这时要写一个特判如果是第一个那么直接输入就好了,接下来每个都判断一下,
 
 如果当前F[j]的值比上一个值大的话就直接加上当前输入的值
 

if (f[j]>f[j-1])f[j]+=ad;


如果比上一个值小的话,那么
 

if (f[j]<f[j-1])
{
     f[j]=f[j-1]+ad;
     g[j]=g[j-1]; 
}

否则就只剩下相等了
 

f[j]=f[j-1]+ad;  //
g[j]=(g[j]+g[j-1])%1000000007;//mod


如果大于的话,路径数不变

如果小于的话,路径数等于上一条的路径数

如果等于的话,路径数等于上一条的路径数加上这条的路径数

废话不多说,献上本蒟蒻的


80分

代码 :

#include<bits/stdc++.h>
using namespace std;
long long f[2001],g[2001];  
int n,m,ad; 
int hans()
 {
     for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {  
            cin>>ad; 
            if (i==1&&j==1) f[j]=ad; 
            else
            {
                if (f[j]>f[j-1])f[j]+=ad;
                else
                {
                    if (f[j]<f[j-1])
                    {
                        f[j]=f[j-1]+ad; 
                        g[j]=g[j-1]; 
                    }
                    else
                    {
                        f[j]=f[j-1]+ad;  
                        g[j]=(g[j]+g[j-1])%1000000007;
                    }
                }
            }
        }
    }
 }
int main()
{
    cin>>n>>m;
    g[1]=1;
    hans();
    cout<<f[m]<<endl; 
    cout<<g[m]<<endl;
    return 0;
}


我当时百思不得其解为什么只得了80分
直到我听安老师讲了一遍,(才恍然大悟),具体就不解释了想知道的话去安老师的博客里看一眼吧


最后献上 100 分代码

#include<bits/stdc++.h>
using namespace std;
long long f[2001],g[2001];  //最大值和路径数,注意要开 LL
int n,m,ad; 
int hans()
 {
     for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {  //n*m个
            cin>>ad; //当前值
            if (i==1&&j==1) f[j]=ad; //特判第一个格子
            else
            {
                if (f[j]>f[j-1])f[j]+=ad;
                else
                {
                    if (f[j]<f[j-1])
                    {
                        f[j]=f[j-1]+ad; 
                        g[j]=g[j-1]; //上一条路径数
                    }
                    else
                    {
                        f[j]=f[j-1]+ad;  //
                        g[j]=(g[j]+g[j-1])%1000000007;
                    }//一定要先取模否则会超时
                }
            }
        }
    }
 }
int main()
{
    cin>>n>>m;
    memset(f,0xFA,sizeof(f)); //坑我二十分
    g[1]=1;
    hans();
    cout<<f[m]<<endl;  //输出
    cout<<g[m]<<endl;
    return 0;
}


 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值