zoukankan      html  css  js  c++  java
  • ZOJ 3877 Earthstone Keeper(最短路)

    本题如果去掉怪物选项就是双关键字最短路。

    问题是现在多了一个怪物选项,因为这个怪物选项被杀死后他不会复生,因此我们不能重复计算这个值的答案。

    所以对于每条过来的路,前面一个点遇到的怪物的后面的点就不用计算了,也就是去重。

    根据这个思路,我们可以得到我们想要干的是当枚举到当前点,我们希望计算出他的cost然后减去前一个点由怪物造成的cost。

    所以怪物这个点是特殊的点,普通点和普通点就是按规则连边,因为他们是相邻的,去重比较容易。

    我们多考虑一种连边,因为题目告诉我们怪物是不可能相邻的,这个信息显然是有自己的道理,也给我们带来启发。

    当我们枚举到怪物点的时,我们将他上下左右这四个点分别连单向边,时间为2,cost就是终点的cost-起点的cost

    这样就成功跳过了怪物类的点

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=2e6+10;
    const int mod=1e9+7;
    int n,m;
    char g[550][550];
    int sx,sy,ex,ey;
    int dx[]={-1,0,1,0};
    int dy[]={0,1,0,-1};
    vector<pll> num;
    int h[N],ne[N],e[N],idx;
    int cost[N],w[N];
    int st[N];
    int dis[N][2];
    struct node{
        int x,y;
        int id;
        bool operator <(const node &t) const{
            if(x==t.x)
                return y>t.y;
            return x>t.x;
        }
    };
    void add(int a,int b,int c,int d){
        e[idx]=b,ne[idx]=h[a],cost[idx]=c,w[idx]=d,h[a]=idx++;
    }
    bool check(int x,int y){
        if(x>=0&&x<n&&y>=0&&y<m){
            if(g[x][y]!='#')
                return true;
        }
        return false;
    }
    int solve(int x,int y){
        int res=0;
        if(g[x][y]>='a'&&g[x][y]<='z')
            res+=(g[x][y]-'a'+1);
        int i;
        for(i=0;i<4;i++){
            int a=x+dx[i];
            int b=y+dy[i];
            if(!check(a,b))
                continue;
            if(g[a][b]>='A'&&g[a][b]<='Z')
                res+=(g[a][b]-'A'+1);
        }
        return res;
    }
    int get(int a,int b,int c,int d){
        int res=solve(c,d);
        int i,j;
        for(i=0;i<4;i++){
            int x=dx[i]+a;
            int y=dy[i]+b;
            if(check(x,y)){
                if(g[x][y]>='A'&&g[x][y]<='Z'){
                    for(int k=0;k<4;k++){
                        int tmp1=dx[k]+x;
                        int tmp2=dy[k]+y;
                        if(check(tmp1,tmp2)){
                            if(tmp1==c&&tmp2==d){
                                res-=(g[x][y]-'A'+1);
                            }
                        }
                    }
                }
            }
        }
        return res;
    }
    void dij(){
        int ans1,ans2;
        priority_queue<node> q;
        q.push({0,0,sx*m+sy});
        int i;
        for(i=0;i<=n*m;i++){
            st[i]=0;
            dis[i][1]=0x3f3f3f3f;
            dis[i][0]=0x3f3f3f3f;
        }
        dis[sx*m+sy][0]=dis[sx*m+sy][1]=0;
        while(q.size()){
            auto t=q.top();
            q.pop();
            if(st[t.id])
                continue;
            st[t.id]=1;
            if(t.id==ex*m+ey){
                ans1=t.x;
                ans2=t.y;
                break;
            }
            for(i=h[t.id];i!=-1;i=ne[i]){
                int j=e[i];
                if(dis[j][0]>dis[t.id][0]+cost[i]){
                    dis[j][0]=dis[t.id][0]+cost[i];
                    dis[j][1]=dis[t.id][1]+w[i];
                    q.push({dis[j][0],dis[j][1],j});
                }
                else if(dis[j][0]==dis[t.id][0]+cost[i]&&dis[j][1]>dis[t.id][1]+w[i]){
                    dis[j][1]=dis[t.id][1]+w[i];
                    q.push({dis[j][0],dis[j][1],j});
                }
            }
        }
        printf("%d %d
    ",ans1,ans2);
    }
    int main(){
        //ios::sync_with_stdio(false);
        int t;
        cin>>t;
        while(t--){
            scanf("%d%d",&n,&m);
            int i,j;
            idx=0;
            for(i=0;i<=n*m;i++){
                h[i]=-1;
            }
            scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
            sx--,sy--,ex--,ey--;
            for(i=0;i<n;i++)
                scanf("%s",g[i]);
            for(i=0;i<n;i++){
                for(j=0;j<m;j++){
                    int k;
                    if(g[i][j]=='#')
                        continue;
                    if(g[i][j]>='A'&&g[i][j]<='Z'){
                        num.clear();
                        for(k=0;k<4;k++){
                            int x=i+dx[k];
                            int y=j+dy[k];
                            if(check(x,y)){
                                num.push_back({x,y});
                            }
                        }
                        for(k=0;k<(int)num.size();k++){
                            for(int l=0;l<(int)num.size();l++){
                                if(k==l)
                                    continue;
                                int tmp1=num[k].first*m+num[k].second;
                                int tmp2=num[l].first*m+num[l].second;
                                add(tmp1,tmp2,get(num[k].first,num[k].second,num[l].first,num[l].second),2);//计算到下个点的代价
                            }
                        }
                    }
                    else{
                        for(int k=0;k<4;k++){
                            int x=i+dx[k];
                            int y=j+dy[k];
                            if(!check(x,y))
                                continue;
                            if(g[x][y]>='A'&&g[x][y]<='Z')
                                continue;
                            add(i*m+j,x*m+y,solve(x,y),1);
                        }
                    }
                }
            }
            dij();
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    Android开发(十五)-Service和BroadcastReceiver
    Android开发(十四)-ContentProvider数据共享
    Android开发(十三)-图形与图像处理
    Android开发(十二)-Android应用资源
    Android开发(十一)-Intent和IntentFilter通信
    Android开发(十)-Activity和Fragment
    Android开发(九)-事件机制
    模拟面试
    二叉堆
    面试
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13766693.html
Copyright © 2011-2022 走看看