HDU 2416 POJ 3346 Treasure of the Chimp Island(最短路)

题意:问能否从城外进入城堡,并取得宝藏。求取得宝藏所需的最短时间。。

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;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值