zl程序教程

您现在的位置是:首页 >  其它

当前栏目

小明在边塞

小明
2023-09-27 14:28:26 时间

小明在边塞

题目大意

从左上角走到右下角,只能向下或右走。
平面上一些点上有敌军阻拦小明经过(1),若要经过这些有敌军的点,则需花费单位为1的体力值消灭该点上的敌军。同时,在另一些点上有能量药丸(2),经过该点服用能量药丸则可增加单位为1的体力值。
初始体力值为0。
求走完后所剩的最大的体力值。

输入样例

5 5
0 1 1 1 1
0 1 2 1 0
0 2 0 1 1
0 0 2 0 0
0 0 0 0 0 

输出样例

2

数据范围

对于30%的数据,1≤n,m≤10
对于80%的数据,1≤n,m≤100
对于100%的数据,1≤n,m≤500

思路

这道题我们可以用dp来做。
因为题目说明只能向下或向右走,就是说只能从上面或从左边走过来。
那么动态转移方程就很好设了:
f [ i ] [ j ] = m a x ( f [ i − 1 ] [ j ] , f [ i ] [ j − 1 ] ) + a [ i ] [ j ] f[i][j]=max(f[i-1][j],f[i][j-1])+a[i][j] f[i][j]=max(f[i1][j],f[i][j1])+a[i][j]
f [ i ] [ j ] f[i][j] f[i][j]为走到点 i j ij ij所剩最大体力值)

代码

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,f[501][501],a[501][501];
int main()
{
	//freopen("b.in","r",stdin);
	//freopen("b.out","w",stdout);
	memset(f,-127/3,sizeof(f));//处理体力值为负情况
	scanf("%d%d",&n,&m);//读入
	for (int i=1;i<=n;i++)
	for (int j=1;j<=m;j++)
	{
		scanf("%d",&a[i][j]);//读入
		if (a[i][j]==1) a[i][j]=-1;//标记
		else if (a[i][j]==2) a[i][j]=1;//标记
	}
	f[1][0]=0;//赋初值
	f[0][1]=0;//赋初值
	for (int i=1;i<=n;i++)
	for (int j=1;j<=m;j++)
	f[i][j]=max(f[i-1][j],f[i][j-1])+a[i][j];//动态转移方程
	printf("%d",f[n][m]);//输出
	//fclose(stdin); 
	//fclose(stdout);
	return 0;
}