Tarjan+dp
建图: 矩阵中的每一个点作为一个节点,分别指向右边和下面不是#的点,单向建边,如果遇到*, 要多加一条指向*传送的点的单向边。强连通图内的所有权值都是可取的,缩点之后,图会变成一个森林,用dfs搜索,并用dp数组记忆化数据,下次dfs到这个点时,直接取dp值即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
const int MaxnN = 40*40+10;
const int MaxnE = 40*40*40*40+10;
const int INF = 0x3f3f3f3f;
const int Mod = 1e9+7;
vector <int> G[MaxnN], vG[MaxnN];
int dfn[MaxnN], low[MaxnN], scc, num[MaxnN];
int cost[MaxnN], Ncost[MaxnN], dp[MaxnN];
int Stack[MaxnN], Top, indx;
int n, m;
char s[MaxnN][MaxnN];
void Tarjan(int u) {
dfn[u] = low[u] = ++indx;
Stack[Top++] = u;
int len = G[u].size();
for(int i = 0; i < len; ++i) {
int v = G[u][i];
if(!dfn[v]) {
Tarjan(v);
low[u] = min(low[u], low[v]);
} else if(!num[v]) low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u]) {
scc++;
int v;
do {
v = Stack[--Top];
num[v] = scc;
Ncost[scc] += cost[v];
} while(u != v);
}
}
void dfs(int u) {
if(dp[u]) return;
int len = vG[u].size(), sum = 0;
for(int i = 0; i < len; ++i) {
int v = vG[u][i];
if(!dp[v]) dfs(v);
sum = max(sum, dp[v]);
}
dp[u] = sum+Ncost[u];
}
int id(int x, int y) {
return (x*m+y);
}
int main(void)
{
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
for(int i = 0; i < n; ++i) scanf("%s", s[i]);
for(int i = 0; i <= n*m; ++i) G[i].clear();
int x, y;
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j) {
if(s[i][j] == '#') {
cost[id(i, j)] = 0;
} else {
if(s[i][j] == '*') {
cost[id(i, j)] = 0;
scanf("%d%d", &x, &y);
if(s[x][y] != '#') G[(id(i, j))].push_back(id(x, y));
}
else cost[id(i, j)] = s[i][j]-'0';
if(i+1 < n && s[i+1][j] != '#') G[id(i, j)].push_back(id(i+1, j));
if(j+1 < m && s[i][j+1] != '#') G[id(i, j)].push_back(id(i, (j+1)));
}
}
}
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(num, 0, sizeof(num));
memset(Ncost, 0, sizeof(Ncost));
scc = Top = indx = 0;
for(int i = 0; i < n*m; ++i) if(!dfn[i]) Tarjan(i);
for(int i = 1; i <= scc; ++i) vG[i].clear();
for(int i = 0; i < n*m; ++i) {
int len = G[i].size();
for(int j = 0; j < len; ++j) {
int v = G[i][j];
if(num[i] != num[v]) vG[num[i]].push_back(num[v]);
}
}
memset(dp, 0, sizeof(dp));
dfs(num[0]);
printf("%d\n", dp[num[0]]);
}
return 0;
}
浙公网安备 33010602011771号