题目:http://acm.hdu.edu.cn/showproblem.php?pid=1044
题目大概意思就是一个迷宫L步之内找价值最多的宝石并且到出口。
最开始我用了dfs LTE。bfs我感觉不适用这个题。求最大值肯定是要类似于dp的思想,搜索里面肯定是dfs才能实现。然后发现其实这就是,这几个宝石可以当做路口,然后每个路口加个分,问L步之内最多多少分。也就是可以当成树。然后就是建树,每个路口之间都有很多路。当然是要最短路喽。然后最短路就可以用bfs解决(快啊)。然后就用bfs遍历一次所有点。然后再用dfs进行搜索。注意value【M+1】记得初始化。因为value是当宝石价值,但是dfs中M点(出口)最后一次也会加一次。不初始化,假设上次宝石数比这次多久出问题了。这道题因为这个bug卡了我很久。尴尬。
#include<bits/stdc++.h>
#define PI 3.1415926
#define INF 1e18
#define inf 1e9
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
const int _max = 55;
struct node{
int x,y;
int step;
void init(int x,int y,int step){
this->x=x;
this->y=y;
this->step=step;
}
};
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
int value[_max];
char mp[_max][_max];
char vis[_max][_max];
int n_mp[_max][_max];
bool n_vis[_max];
int w,h,l,m;
int ans,sum;
queue<node> q;
bool outside(node n1){
if(mp[n1.y][n1.x] == '*') return false;
else if(n1.y < 1) return false;
else if(n1.y > h) return false;
else if(n1.x > w) return false;
else if(n1.x < 1) return false;
else if(!vis[n1.y][n1.x]) return false;
return true;
}
void bfs(int a,int x,int y){
while(!q.empty()) q.pop();
node now,next;
now.init(x,y,0);
q.push(now);
vis[y][x] = false;
while(!q.empty()){
now = q.front();
q.pop();
for(int i = 0 ; i < 4 ; i++){
next.init(now.x+dx[i],now.y+dy[i],now.step+1);
if(next.step > l) continue;
if(!outside(next)) continue;
char c = mp[next.y][next.x];
if(c == '@') n_mp[a][0]=next.step;
else if(c == '<') n_mp[a][m+1]=next.step;
else if(c >= 'A' && c <= 'J') n_mp[a][c-'A'+1]=next.step;
vis[next.y][next.x] = false;
q.push(next);
}
}
return ;
}
void dfs(int n,int cnt,int step){
if(step > l) return ;
if(sum == ans) return ;
if(n == m+1){
ans = max(cnt,ans);
return ;
}
for(int i = 1 ; i <= m+1 ; i++){
if(!n_vis[i]) continue;
if(!n_mp[n][i]) continue;
n_vis[n] = false;
dfs(i,cnt+value[i],step+n_mp[n][i]);
n_vis[i] = true;
}
return ;
}
int main(){
int T,t=1;
cin>>T;
while(T--){
cin>>w>>h>>l>>m;
sum = 0;
memset(n_mp,0,sizeof(n_mp));
memset(n_vis,true,sizeof(n_vis));
memset(value,0,sizeof(value));
for(int i = 1 ; i <= m ; i++){
cin>>value[i];
sum += value[i];
}
for(int y = 1 ; y <= h ; y++)
for(int x = 1 ; x <= w ; x++)
cin>>mp[y][x];
for(int y = 1 ; y <= h ; y++)
for(int x = 1 ; x <= w ; x++){
memset(vis,true,sizeof(vis));
char c = mp[y][x];
if(c == '@') bfs(0,x,y);
else if(c == '<') bfs(m+1,x,y);
else if(c >= 'A' && c <= 'J') bfs(c-'A'+1,x,y);
}
/* for(int y = 0 ; y <= m+1 ; y++){
for(int x = 0 ; x <= m+1 ; x++){
cout<<n_mp[y][x]<<" ";
}
cout<<endl;
}*/
cout<<"Case "<<t++<<":"<<endl;
if(n_mp[0][m+1] > l ){
cout<<"Impossible"<<endl;
continue;
}
ans = -inf;
dfs(0,0,0);
if(ans == -inf)
cout<<"Impossible"<<endl;
else
cout<<"The best score is "<<ans<<"."<<endl;
if(T)cout<<endl;
}
return 0;
}