钻石(简单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 */