钻石(简单dp)

第3题     钻石 查看测评数据信息

有一个R行C列的网格,我们用(i,j)表示第i行第j列的格子。

有k个钻石,第i个钻石所在的格子是(r[i],c[i]),价值是v[i]。

你要从左上角格子(1,1)出发,每一步可以向下或向右走一格,最终要到达右下角格子(R,C)。

每进入一个有钻石的格子,你就可以收集到该钻石的价值。

但是有一个规定是:同一行的所有格子当中,你最多只能收集3个钻石。

比如你可以在同一行中到达4个或者更多有钻石的格子,但是你最多只能收集3个钻石。

求能收集到的钻石的最大价值。

出发点格子(1,1)和终点格子(R,C)如果有钻石,也是按照上面的规则。

 

输入格式

 

第一行,三个整数R,C,k。1<=R,C<=3000, 1<=K<=min(200000,R*C)。

接下来有k行,第i行有3个整数: r[i],c[i],v[i]。1<=r[i]<=R, 1<=c[i]<=C, 1<=v[i]<=10^9。

同一个格子最多只有一个钻石。

 

输出格式

 

一个整数。

 

输入/输出例子1

输入:

2 2 3

1 1 3

2 1 4

1 2 5

 

输出:

8

 

输入/输出例子2

输入:

2 5 5

1 1 3

2 4 20

1 2 1

1 3 4

1 4 2

 

输出:

29

 

样例解释

 

 

 

比较水的一题,考场切出来了就不讲了。唯一值得注意的是开longlong

#include <bits/stdc++.h>
#define int long long 
using namespace std;
const int N=3005;

int n, m, k, a[N][N], x, y, c, ans=0;
int f[N][N][5];
signed main()
{
	scanf("%lld%lld%lld", &n, &m, &k);
//	memset(a, 0, sizeof a);
//	memset(f, 0, sizeof f);
	while (k--) 
	{
		scanf("%lld%lld%lld", &x, &y, &c);
		a[x][y]=c;
		f[x][y][1]=c;
	}
	
	for (int i=1; i<=n; i++)
	{
		for (int j=1; j<=m; j++)
		{
			for (int k=0; k<=3; k++)
			{
				f[i][j][k]=max(f[i][j][k], f[i][j-1][k]);
				for (int k2=0; k2<=3; k2++) f[i][j][k]=max(f[i][j][k], f[i-1][j][k2]);
				
				if (k-1>=0) 
				{
					f[i][j][k]=max(f[i][j][k], f[i][j-1][k-1]+a[i][j]);
					for (int k2=0; k2<=3; k2++) f[i][j][k]=max(f[i][j][k], f[i-1][j][k2]+a[i][j]);
				}
			}
		}
	}
	
	/*for (int i=1; i<=n; i++)
	{
		for (int j=1; j<=m; j++)
		{
			cout<<max(f[i][j][3], max(f[i][j][1], f[i][j][2]))<<" ";
		}
		cout<<endl;
	}*/
		
			
	for (int k=0; k<=3; k++) ans=max(ans, f[n][m][k]);
	printf("%lld", ans);
	return 0;
}
/*
3 3 4
1 2 4
2 1 5
2 3 1
3 2 6


*/

  

posted @ 2024-07-13 19:51  cn是大帅哥886  阅读(9)  评论(0编辑  收藏  举报