题意:问能否从城外进入城堡,并取得宝藏。求取得宝藏所需的最短时间。。
1,边界有字母,或者#表示入口。#表示从这里进入可以获得0个炸弹,A表示可以获得1个炸弹,B两个。。。
2, 星号表示障碍,不可通过。点表示同路,通过的时间为0。1-9表示从这点通过需要话费的时间,当然这个点可以用炸弹掉,通过的时间为0。
开始的时候我按照普通的做法,在边界上找到一个入口就搜一次,结果TLE,
然后换成从宝藏开始往外搜,WA,
最后看了一下题,发现题中有说明,一次只能带一次炸药,即只能从边界直接往里走,不能边界走向边界。加了这个条件之后就AC了。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> using namespace std; const int N = 109; const int INF =0x3f3f3f3f; int n,m; int dp[N][N][30]; bool visit[N][N][30]; char map[N][N]; bool init() { n=0; while(1) { gets(map[n]); if(map[n][0]=='-') return false; if(strlen(map[n])==0) break; n++; } m = strlen(map[0]); return true; } int dx[]={0,0,-1,1}; int dy[]={-1,1,0,0}; struct nod{ int dis; int x,y,dep; bool operator <(const nod t) const { return dis>t.dis; } }; priority_queue<nod> que; bool oor(int x,int y) { if(x<0||x>=n) return false; if(y<0||y>=m) return false; return true; } void deal() { memset(dp,INF,sizeof(dp)); memset(visit,false,sizeof(visit)); int enx,eny; for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(map[i][j]=='$') { enx=i,eny=j; } while(!que.empty()) que.pop(); nod e,t; e.dep=0;e.dis=0;e.x=enx,e.y=eny; que.push(e); while(!que.empty()) { e = que.top(); que.pop(); if(visit[e.x][e.y][e.dep]) continue; visit[e.x][e.y][e.dep] = true; dp[e.x][e.y][e.dep] = e.dis; if(e.x==0||e.y==0||e.x==n-1||e.y==m-1) continue; for(int i=0;i<4;i++) { int tx=e.x+dx[i],ty=e.y+dy[i]; if(!oor(tx,ty)||map[tx][ty]=='*') continue; if(map[tx][ty]>='0'&&map[tx][ty]<='9') { t.dis = e.dis+map[tx][ty]-'0'; t.dep = e.dep; t.x = tx,t.y = ty; if(!visit[tx][ty][t.dep]&&dp[tx][ty][t.dep]>t.dis) que.push(t); t.dis = e.dis; t.dep = e.dep+1; t.x = tx,t.y = ty; if(!visit[tx][ty][t.dep]&&dp[tx][ty][t.dep]>t.dis&&t.dep<=26) que.push(t); } else { t.dis = e.dis; t.dep = e.dep; t.x = tx,t.y = ty; if(dp[tx][ty][t.dep]>t.dis) que.push(t); } } } } int fin(int x,int y) { int ans = INF; int d = map[x][y]=='#'?0:map[x][y]-'A'+1; for(int i=0;i<=d;i++) ans=min(dp[x][y][d],ans); return ans; } void solve() { deal(); int ans=INF; for(int i=1;i<n;i++) { if(map[i][0]!='*') ans=min(fin(i,0),ans); if(map[i][m-1]!='*') ans=min(fin(i,m-1),ans); } for(int i=1;i<m;i++) { if(map[0][i]!='*') ans=min(fin(0,i),ans); if(map[n-1][i]!='*') ans=min(fin(n-1,i),ans); } if(ans==INF) printf("IMPOSSIBLE\n"); else printf("%d\n",ans); } int main() { freopen("in.txt","r",stdin); while(1) { if(!init()) break; solve(); } return 0; }