SenseTime Ace Coder Challenge 暨 商湯線上程式設計挑戰賽 A.雙人取數
阿新 • • 發佈:2018-12-16
有一款雙人遊戲,遊戲的地圖是一張 n \times mn×m的平面,其中玩家 A 從地圖的左上角出發,通過向右和向下走的方式走到右下角,玩家 B 從右上角出發,通過向左和向下的方式走到左下角(每次只能走到上下左右相鄰的至多四個格子)。
每個格子有一個分數,玩家走到格子上就會獲得這個分數,當一個玩家得到這個分數後,格子的分數就會自動變為 00。遊戲最後的得分是兩個人獲得分數的總和。
即使兩個人同時進入一個格子,這個格子上的分數也只會被計入一次。
現在希望你幫忙計算出,這個遊戲能獲得的最高分是多少。
輸入格式
輸入第一行一個整數 TT。表示測試資料組數。
接下來輸入 TT 組資料。每組資料按照下面的規則輸入。
對於每組資料第一行輸入兩個整數 nn,mm,代表遊戲地圖的長和寬。
然後接下來的 nn 行每行輸入 mm 個整數,代表地圖上每個格子的分數。
1 \le T \le 151≤T≤15,3 \le n,m \le 10003≤n,m≤1000。
每個格子分數絕對值 \le 1000≤1000。
輸出格式
對於第i
組資料,輸出格式形如"Case #i: x"
(輸出不含引號),其中x
表示該組資料對應的遊戲最高分。
題解:
重合的部分一定是連續的一行幾個,或連續的一列幾個。
字首和優化一下就行了。
#include <bits/stdc++.h> #ifdef LOCAL #define debug(x) cout<<#x<<" = "<<(x)<<endl; #else #define debug(x) 1; #endif #define chmax(x,y) x=max(x,y) #define chmin(x,y) x=min(x,y) #define lson id<<1,l,mid #define rson id<<1|1,mid+1,r #define lowbit(x) x&-x #define mp make_pair #define pb push_back #define fir first #define sec second using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int MOD = 1e9 + 7; const double PI = acos (-1.); const double eps = 1e-10; const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3f; const int MAXN = 5e5 + 5; int a[1111][1111]; int d1[1111][1111][2]; // 0 上 1 左 int d2[1111][1111][2]; // 0 上 1 右 int d3[1111][1111][2]; // 0 下 1 右 int d4[1111][1111][2]; // 0 下 1 左 int pre1[1111][1111], pre2[1111][1111]; int maxn[1111]; int main() { #ifdef LOCAL freopen ("input.txt", "r", stdin); #endif int T, cas = 1; cin >> T; while (T--) { int n, m; scanf ("%d %d", &n, &m); for (int i = 0; i <= n + 1; i++) for (int j = 0; j <= m + 1; j++) for (int k = 0; k < 2; k++) { d1[i][j][k] = d2[i][j][k] = d3[i][j][k] = d4[i][j][k] = -INF; } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf ("%d", &a[i][j]); d1[1][1][0] = d1[1][1][1] = a[1][1]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { chmax (d1[i][j][0], max(d1[i - 1][j][0], d1[i - 1][j][1]) + a[i][j]); chmax (d1[i][j][1], max(d1[i][j - 1][0], d1[i][j - 1][1]) + a[i][j]); } } d2[1][m][0] = d2[1][m][1] = a[1][m]; for (int i = 1; i <= n; i++) { for (int j = m; j >= 1; j--) { chmax (d2[i][j][0], max(d2[i - 1][j][0], d2[i - 1][j][1])+ a[i][j]); chmax (d2[i][j][1], max(d2[i][j + 1][0], d2[i][j + 1][1])+ a[i][j]); } } d3[n][m][0] = d3[n][m][1] = a[n][m]; for (int i = n; i >= 1; i--) { for (int j = m; j >= 1; j--) { chmax (d3[i][j][0], max(d3[i + 1][j][0], d3[i + 1][j][1])+ a[i][j]); chmax (d3[i][j][1], max(d3[i][j + 1][0], d3[i][j + 1][1])+ a[i][j]); } } d4[n][1][0] = d4[n][1][1] = a[n][1]; for (int i = n; i >= 1; i--) { for (int j = 1; j <= m; j++) { chmax (d4[i][j][0], max(d4[i + 1][j][0], d4[i + 1][j][1])+ a[i][j]); chmax (d4[i][j][1], max(d4[i][j - 1][0], d4[i][j - 1][1])+ a[i][j]); } } // debug(d2[2][3][1]) int ans = -INF; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) pre1[i][j] = pre1[i][j - 1] + a[i][j]; for (int j = 1; j <= m; j++) for (int i = 1; i <= n; i++) pre2[i][j] = pre2[i - 1][j] + a[i][j]; for (int i = 1; i <= n; i++) { maxn[m + 1] = -INF; for (int j = m; j >= 1; j--) { maxn[j] = maxn[j + 1]; for (int k = 0; k < 2; k++) for (int l = 0; l < 2; l++) if (k != 1 || l != 1) chmax(ans, maxn[j] + d1[i][j][k] + d4[i][j][l] - a[i][j] * 2 - pre1[i][j - 1]); for (int k = 0; k < 2; k++) for (int l = 0; l < 2; l++) if (k != 1 || l != 1) chmax (maxn[j], d2[i][j][k] + d3[i][j][l] - a[i][j] * 2 + pre1[i][j]); chmax (ans, d1[i][j][0] + d3[i][j][0] + d2[i][j][1] + d4[i][j][1] - a[i][j] * 3); chmax (ans, d1[i][j][1] + d3[i][j][1] + d2[i][j][0] + d4[i][j][0] - a[i][j] * 3); // debug(ans) } } for (int j = 1; j <= m; j++) { maxn[n + 1] = -INF; for (int i = n; i >= 1; i--) { maxn[i] = maxn[i + 1]; for (int k = 0; k < 2; k++) for (int l = 0; l < 2; l++) if (k != 0 || l != 0) chmax(ans, maxn[i] + d1[i][j][k] + d2[i][j][l] - a[i][j] * 2 - pre2[i - 1][j]); for (int k = 0; k < 2; k++) for (int l = 0; l < 2; l++) if (k != 0 || l != 0) chmax (maxn[i], d4[i][j][k] + d3[i][j][l] - a[i][j] * 2 + pre2[i][j]); } } printf ("Case #%d: %d\n", cas++, ans); } return 0; }