hdu 4771 Stealing Harry Potter's Precious

本文介绍了一种用于解决N×M地图中从起点出发,寻找特定数量宝藏的最短路径问题的方法。通过状态空间搜索,算法遍历地图,考虑宝藏收集情况,最终求得最短步数。

        题意:N*M的地图,@是起点,#不能走,去拿k个宝藏,求最短步数。

        思路:状态空间搜索。前两维是横纵坐标,第三维是宝藏的取得情况,爆搜过去就好了。


#include <stdio.h>
#include <queue>
#include <memory.h>

using namespace std;

#define INF 1000000000

char mp[110][110];

int vis[110][110][16];

struct node{
    int nn;int mm;int s;
    node(int a,int b,int c){
        nn=a;mm=b;s=c;
    }
};

int dirn[]={-1,1,0,0};
int dirm[]={0,0,-1,1};

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0)break;
        memset(mp,0,sizeof(mp));
        
        int startn,startm;
        for(int i=1;i<=n;i++){
            scanf("%s",mp[i]+1);
            for(int j=1;j<=m;j++){
                for(int l=0;l<16;l++)vis[i][j][l]=INF;
                if(mp[i][j]=='@'){
                    startn=i; startm=j;
                }
            }
        }
        
        int k;
        scanf("%d",&k);
        for(int i=1;i<=k;i++){
            int nn,mm;
            scanf("%d%d",&nn,&mm);
            mp[nn][mm]=i;
        }
        
        queue<node> que; 
        node start(startn,startm,0);
        que.push(start);
        
        int ans=INF;
        int target=(1<<k)-1;
        vis[startn][startm][0]=0;
        while(!que.empty()){
            node cur=que.front(); que.pop();
            int curn=cur.nn;
            int curm=cur.mm;
            int curs=cur.s;
            
            for(int i=0;i<4;i++){
                int newn=curn+dirn[i];
                int newm=curm+dirm[i];
                int news=curs;
                if(mp[newn][newm]==0||mp[newn][newm]=='#')continue;
                
                if(mp[newn][newm]<=4){
                    news=curs| ( 1<<(mp[newn][newm]-1));
                }
                    if(vis[curn][curm][curs]+1<vis[newn][newm][news]){
                        node nd(newn,newm,news);
                        vis[newn][newm][news]=vis[curn][curm][curs]+1;
                        que.push(nd);
                        if(news==target)ans=min(ans,vis[curn][curm][curs]+1);
                    }
            }
        }
        if(ans==INF){
            printf("-1\n");
        }else{
            printf("%d\n",ans);
        }
    }
    return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值