2011年的北邮多校联合赛H题
BUPT 202 chocolate mashine
学校的老OJ要挂代理才能上 所以这里给一个hust上的题目链接:
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70168#problem/J
均从1开始计数
dp[i][j]表示以第i行第j列小格为巧克力最右下角时 金钱的最大值
视值小于K的小格为“阻挡”
若(i, j)本身为“阻挡” 则dp[i][j] = 0
若(i, j)的上面一格和左边一格均有“阻挡” 则dp[i][j] = a[i][j]
若仅上面一格为“阻挡” 则 dp[i][j] = 从当前格开始往左边加 直到遇到边界或“阻挡”
若仅左边一格为“阻挡” 则 dp[i][j] = 从当前格开始往上面加 直到遇到边界或“阻挡”
若上和左均无阻挡 则dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + a[i][j]
然后不断更新dp[i][j]中的最大值
不难 就是按我这个思路走的话比较繁琐 wa了4炮TAT
#include <cstdio> #include <cstdlib> #include <ctime> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> #include <stack> #include <set> #include <queue> #include <vector> using namespace std; typedef long long ll; const int maxn = 3010; ll dp[maxn][maxn]; int a[maxn][maxn]; int main() { //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); while(T--) { int n, m, k; scanf("%d%d%d", &n, &m, &k); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) scanf("%d", &a[i][j]); ll ans = 0; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) { if(a[i][j] < k) dp[i][j] = 0; else { if(dp[i-1][j] == 0 && dp[i][j-1] == 0) dp[i][j] = a[i][j]; else if(i-1 >= 1 && dp[i-1][j] == 0) { dp[i][j] = a[i][j]; int t = 1; while(j - t >= 1 && dp[i][j-t] != 0) { dp[i][j] += a[i][j-t]; t++; } } else if(j - 1 >= 1 && dp[i][j-1] == 0) { dp[i][j] = a[i][j]; int t = 1; while(i - t >= 1 && dp[i-t][j] != 0) { dp[i][j] += a[i-t][j]; t++; } } else { dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + a[i][j]; } } if(dp[i][j] > ans) ans = dp[i][j]; } printf("%I64d\n", ans); } return 0; }
时间: 2024-10-28 08:30:44