hdu5025 (2014广州网赛1004)Saving Tang Monk

        题意:类似走迷宫的一个题,给一个n*n的地图,从K开始走到T,标#号的地方不能走。走的过程中,要按顺序拿m种钥匙(在地图中是数字,每种可能有多把),如果遇到蛇S,需要花1的额外时间把它打死。输出走到终点的最短时间。

        思路:状态空间搜索。如果把钥匙的取得情况和蛇的生存情况也看成状态,就简单多了。状态第一、二维是行和列。钥匙最多9,需要按顺序拿,所以第三维开10就足够了。蛇的生存情况可以用5位二进制表示,也就是第四维开32。然后用优先队列搜。比赛的时候这题A出来真是扬眉吐气~


#include <iostream>               
#include <stdio.h>               
#include <cmath>               
#include <algorithm>               
#include <iomanip>               
#include <cstdlib>               
#include <string>               
#include <string.h>               
#include <vector>               
#include <queue>               
#include <stack>               
#include <map>             
#include <assert.h>    
#include <set>             
#include <ctype.h>                    
#define ll long long           
#define max3(a,b,c) max(a,max(b,c))           
    
using namespace std;  

char mp[110][110];
int a[110][110][10][32];

int dn[]={-1,1,0,0};
int dm[]={0,0,-1,1};

struct node{
	int nn;
	int mm;
	int key;
	int snk;
	int dis;
	node(int a,int b,int c,int d,int ee){
		nn=a; mm=b; key=c; snk=d; dis=ee;
	}
	bool operator<(node b)const{
		return dis>b.dis;
	}
};

int main(){
	int n,m;
	while(cin>>n>>m){
		if(n==0&&m==0)break;
		memset(a,-1,sizeof(a));
		int snk=0;
		int startn;
		int startm;
		int endn;
		int endm;
		for(int i=1;i<=n;i++){
			scanf("%s",mp[i]+1);
			for(int j=1;j<=n;j++){
				if(mp[i][j]=='K'){
					startn=i;
					startm=j;
				}else if(mp[i][j]=='S'){
					mp[i][j]=snk+'A';
					snk++;
				}else if(mp[i][j]=='T'){
					endn=i;
					endm=j;
				}
			}
		}
		
		node start(startn,startm,0,0,0); a[startn][startm][0][0]=0;
		priority_queue<node> que; que.push(start);
		
		int ans=0;
		while(!que.empty()){
			node cur=que.top(); que.pop();
			int cn=cur.nn;
			int cm=cur.mm;
			int ckey=cur.key;
			int csnk=cur.snk;
			int cdis=cur.dis;
			if(cn==endn&&cm==endm&&ckey==m){
				ans=cdis;
				break;
			}
			
			for(int d=0;d<4;d++){
				int newn=cn+dn[d];
				int newm=cm+dm[d];
				
				if( newn<1||newn>n||newm<1||newm>n )continue;
				if( mp[newn][newm]=='#' )continue;
				if( mp[newn][newm]=='.'||mp[newn][newm]=='T'||mp[newn][newm]=='K' ){
					if(a[newn][newm][ckey][csnk]==-1){
						a[newn][newm][ckey][csnk]=cdis+1;
						node nd(newn,newm,ckey,csnk,cdis+1);
						que.push(nd);
					}
				}
				if( mp[newn][newm]>='A'&&mp[newn][newm]<='E' ){
					int tmp=mp[newn][newm]-'A';
					tmp=(1<<tmp);
					if(tmp&csnk){
						if(a[newn][newm][ckey][csnk]==-1){
							a[newn][newm][ckey][csnk]=cdis+1;
							node nd(newn,newm,ckey,csnk,cdis+1);
							que.push(nd);
						}
					}else{
						if(a[newn][newm][ckey][csnk|tmp]==-1){
							a[newn][newm][ckey][csnk|tmp]=cdis+2;
							node nd(newn,newm,ckey,csnk|tmp,cdis+2);
							que.push(nd);
						}
					}
				}
				
				if( mp[newn][newm]>='1'&&mp[newn][newm]<='9' ){
					int tmp=mp[newn][newm]-'0';
					if(tmp==ckey+1){
						if(a[newn][newm][ckey+1][csnk]==-1){
							a[newn][newm][ckey+1][csnk]=cdis+1;
							node nd(newn,newm,ckey+1,csnk,cdis+1);
							que.push(nd);
						}
					}else{
						if(a[newn][newm][ckey][csnk]==-1){
							a[newn][newm][ckey][csnk]=cdis+1;
							node nd(newn,newm,ckey,csnk,cdis+1);
							que.push(nd);
						}
					}
				}
			}
		}
		if(ans==0){
			cout<<"impossible"<<endl;
		}else{
			cout<<ans<<endl;
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值