解法
看到陷阱只有15个能反应过来是状态DP,但是不知道怎么个DP法……
首先,不考虑能量够不够,每个状态直接用DFS/BFS可以得到一个最终能量值E[s]
,这个状态下能够到但是不在状态里的陷阱集合adjTrap[s]
,还有这个状态能不能出去isAble[s]
这三个东西出来之后就可以DP了,设f为状态s
可以取得的最大能量:
f[s]
初始为-1
- 如果
isAble[s]==true
,那么f[s]=E[s]
- 接下来遍历
adjTrap[s]
里的每一个陷阱i
,如果当前能量E[s]
能通过这个陷阱i,那么可以尝试通过,所以状态转移方程为:f[s] = max(f[s],f[s|(1<<i)])
用从顶向下的记忆化搜索过的,不知道为什么递推版本的过不了,可能跟有的状态的E
是负数有关。
#include <stdio.h>
#include <string>
#include <iostream>
#include <memory.h>
#include <stdlib.h>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
#define MAXN 110
#define NINF -100000
#define INF 65536
using namespace std;
typedef long long lld;
int n,m,e,sx,sy,tx,ty;
int A[MAXN][MAXN], adjTrap[INF], E[INF];
bool mark[MAXN][MAXN], isAble[INF];
vector<pair<int,int>> traps;
map<pair<int,int>,int> idx;
int dx[4] = {0,0,-1,1}, dy[4] = {-1,1,0,0};
int f[INF];
bool isSafe(const int &x, const int &y) {
return x>=0 && x<n && y>=0 && y<m;
}
void bfs(int s) {
int l = traps.size();
memset(mark,0,sizeof(bool)*MAXN*MAXN);
for(int i=0;i<l;++i) {
if((s&(1<<i))==0) {
mark[traps[i].first][traps[i].second] = true;
}
}
queue<pair<int,int>> bfs;
bfs.push(make_pair(sx,sy));
mark[sx][sy] = true;
isAble[s] = false;
E[s] = e;
adjTrap[s] = 0;
while(!bfs.empty()) {
auto a = bfs.front();
bfs.pop();
if(a.first==tx && a.second==ty) isAble[s] = true;
for(int d = 0;d<4;++d) {
int nx = a.first+ dx[d],ny = a.second+ dy[d];
if(isSafe(nx,ny) && !mark[nx][ny] && A[nx][ny]!=NINF) {
mark[nx][ny] = true;
bfs.push(make_pair(nx,ny));
E[s] += A[nx][ny];
} else if (isSafe(nx,ny) && mark[nx][ny] && A[nx][ny]<0) {
adjTrap[s] |= (1<<idx[make_pair(nx,ny)]);
}
}
}
adjTrap[s] ^= s;
}
int solve(int s) {
if(f[s]!=-2) return f[s];
f[s] = -1;
if(isAble[s]) f[s] = E[s];
int l = traps.size();
for(int i=0;i<l;++i) {
if((adjTrap[s]&(1<<i))>0 && E[s]+A[traps[i].first][traps[i].second]>=0)
f[s] = max(f[s],solve(s|(1<<i)));
}
return f[s];
}
int main() {
int t;
scanf("%d",&t);
for(auto round=1;round<=t;++round) {
scanf("%d%d%d%d%d%d%d",&n,&m,&e,&sx,&sy,&tx,&ty);
sx--, sy--, tx--,ty--;
traps.clear();
idx.clear();
for(int i=0;i<n;++i){
for(int j=0;j<m;++j) {
scanf("%d",&A[i][j]);
if (A[i][j]<0 && A[i][j]!=NINF){
idx[make_pair(i,j)] = traps.size();
traps.emplace_back(make_pair(i,j));
}
}
}
int l = traps.size();
int UP = (1<<l);
for(int s = 0;s<UP;++s)
bfs(s);
for(int s=0;s<UP;++s) f[s] = -2;
printf("Case #%d: %d\n",round,solve(0));
}
}