觉得写这道(水)题题解的人挺少的,那我就来发一篇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;
}