题意:找到一个地图中尽量多的宝藏并在尽可能短的时间内走到指定地点。
思路:状态压缩。先预处理出每个宝藏之间的距离,然后状压dp。写代码的时候又犯了把变量名写错的错误。。导致re。
代码如下:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<map>
#include<set>
#include<list>
#include<stack>
#include<algorithm>
#include<queue>
#include<vector>
#include<time.h>
#include<iomanip>
//#include<assert.h>
using namespace std;
const int dir[4][2] = {-1,0,0,1,1,0,0,-1};
int n,m;
char g[505][505];
int dis[20][20];
int id[505][505];
int xx[20];
int yy[20];
int tot;
int x1,y1,x2,y2;
bool vis[505][505];
int dist[505][505];
struct Pos
{
int x,y;
Pos(int x,int y):x(x),y(y){}
};
bool judge(int x,int y)
{
if(x<0||x>=n)return false;
if(y<0||y>=m)return false;
return true;
}
void bfs(int tid,Pos s)
{
memset(dist ,-1,sizeof(dist));
memset(vis,0,sizeof(vis));
dist[s.x][s.y] = 0;
if(id[s.x][s.y]>=0){
dis[tid][id[s.x][s.y]] =dis[id[s.x][s.y]][tid]= 0;
}
queue<Pos> q;
q.push(s);
vis[s.x][s.y] = 1;
while(!q.empty()){
s = q.front();
q.pop();
vis[s.x][s.y] = 0;
if(g[s.x][s.y] == '0'||g[s.x][s.y] == '$'){
for(int i = 0 ;i<4;++i){
int tx = s.x + dir[i][0];
int ty = s.y + dir[i][1];
// assert(tx == s.x+dir[i][0]);
// assert(ty == s.y + dir[i][1]);
if(!judge(tx,ty))continue;
if(g[tx][ty] == '#'||g[tx][ty] == 'W')continue;
if(dist[tx][ty] == -1||dist[tx][ty] > dist[s.x][s.y] + 1){
dist[tx][ty] = dist[s.x][s.y] + 1;
if(!vis[tx][ty]){
q.push(Pos(tx,ty));
vis[tx][ty] = 1;
}
if(id[tx][ty] >=0) dis[tid][id[tx][ty]] = dist[tx][ty];
}
}
continue;
}
Pos nxt = s;
if(g[s.x][s.y] == 'L'){
nxt.y--;
} else if(g[s.x][s.y] == 'R'){
nxt.y++;
} else if(g[s.x][s.y] == 'U'){
nxt.x--;
} else if(g[s.x][s.y] == 'D'){
nxt.x++;
}
int tx = nxt.x;int ty = nxt.y;
if(!judge(nxt.x,nxt.y))continue;
if(g[nxt.x][nxt.y]=='#'||g[nxt.x][nxt.y] == 'W')continue;
if(dist[tx][ty] == -1||dist[tx][ty] > dist[s.x][s.y] + 1){
dist[tx][ty] = dist[s.x][s.y] + 1;
if(!vis[nxt.x][nxt.y]){
vis[nxt.x][nxt.y] = 1;
q.push(nxt);
}
if(id[tx][ty] >=0) dis[tid][id[tx][ty]] = dist[tx][ty];
}
}
}
int dp[15][1<<13];
bool in[15][1<<13];
struct STA{
int p,s;
STA(int p = 0,int s = 0):p(p),s(s){}
};
int cnt(int i)
{
int ret = 0;
while(i){
if(i&1)ret++;
i>>=1;
}
return ret;
}
void solve()
{
xx[0] = x1;yy[0] = y1;
xx[1] = x2;yy[1] = y2;
tot = 2;
id[x1][y1] = 0;id[x2][y2] = 1;
for(int i = 0; i<n;++i){
for(int j = 0;j<n;++j){
if(g[i][j] == '$'){
id[i][j] = tot;
xx[tot] = i;
yy[tot] = j;
if(i == x1&&j == y1)dis[0][tot] = dis[tot][0] = 0;
else if(i == x2 &&j == y2)dis[1][tot] = dis[tot][1] = 0;
tot ++;
}
}
}
for(int i = 0; i<tot;++i){
bfs(i,Pos(xx[i],yy[i]));
}
memset(dp,-1,sizeof(dp));
dp[0][0] = 0;
memset(in,0,sizeof(in));
queue<STA> q;
q.push(STA(0,0));
in[0][0] = 1;
while(!q.empty()){
STA st = q.front();q.pop();
int s = st.s;
in[st.p][st.s] = 0;
for(int i = 0;i<tot;++i){
if(dis[st.p][i] == -1)continue;
int cost = dis[st.p][i];
if(dp[i][s|(1<<i)] == -1 || dp[i][s|(1<<i)]>dp[st.p][s]+cost){
dp[i][s|(1<<i)] = dp[st.p][s]+cost;
if(!in[i][s|(1<<i)]){
q.push(STA(i,s|(1<<i)));
in[i][s|(1<<i)] = 1;
}
}
}
}
int maxn = -1;
int ans = -1;
for(int i = 0 ;i < (1<<tot);++i){
if(dp[1][i] == -1)continue;
int c = cnt(i);
if(c>maxn|| ans == -1 || (c == maxn&&dp[1][i]<ans)){
maxn = c;
ans = dp[1][i];
}
}
if(ans == -1) {
puts("-1");
return;
}
ans += (maxn-2) *2;
printf("%d\n",ans);
}
int main()
{
// freopen("data.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF){
memset(dis,-1,sizeof(dis));
memset(id,-1,sizeof(id));
for(int i = 0; i < n; ++i){
scanf("%s",g[i]);
}
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1--;y1--;x2--;y2--;
solve();
}
return 0;
}