zoukankan      html  css  js  c++  java
  • hdu4308(bfs)

    多校第9题:巧妙的广搜,遇到第一个P的时候,将所有的其他P都压入队列,再搜下去就会接着P开始往下搜,搜到C结束。

    附代码:

    View Code
    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    using namespace std;
    #define V 5010
    char map[V][V];
    bool vis[V][V];
    int dir[4][2]={{1,0},{0,1},{0,-1},{-1,0}};
    struct Node
    {
        int x,y;
        long long step;
    }q[V];
    int r,c,cost;
    long long bfs(int xx,int yy)
    {
        vis[xx][yy]=1;
        int head=0,tail=0;
        q[tail].x=xx;
        q[tail].y=yy;
        q[tail++].step=0;
        while(head<tail)
        {
            xx=q[head].x;
            yy=q[head].y;
            long long ss=q[head++].step;
            for(int i=0;i<4;i++)
            {
                int xxx=xx+dir[i][0];
                int yyy=yy+dir[i][1];
                if(vis[xxx][yyy]==0 && map[xxx][yyy]!='#' && xxx>=0 && xxx<r && yyy>=0 && yyy<c)
                {
                    vis[xxx][yyy]=1;
                    q[tail].x=xxx;
                    q[tail].y=yyy;
                    if(map[xxx][yyy]=='C')
                    {
                        return ss;
                    }
                    if(map[xxx][yyy]=='*')
                    {
                        q[tail++].step=ss+cost;
                    }
                    if(map[xxx][yyy]=='P')
                    {
                        q[tail++].step=ss;
                        for(int i=0;i<r;i++)
                        {
                            for(int j=0;j<c;j++)
                            {
                                if(map[i][j]=='P')
                                {
                                    vis[i][j]=1;
                                    q[tail].x=i;
                                    q[tail].y=j;
                                    q[tail++].step=ss;
                                }
                            }
                        }
                    }
                }
            }
        }
        return -1;
    }
    
    int main()
    {
        long long res;
        while(cin >> r >> c >> cost)
        {
            for(int i=0;i<r;i++)
            {
                scanf("%s",map[i]);
            }
            memset(vis,0,sizeof(vis));
            for(int i=0;i<r;i++)
            {
                for(int j=0;j<c;j++)
                {
                    if(map[i][j]=='Y')
                    {
                        res=bfs(i,j);
                    }
                }
            }
            if(res==-1) cout <<"Damn teoy!" << endl;
            else cout << res << endl;
        }
        return 0;
    }

    该题还有最短路算法:
    给出的地图中,Y为起点,C为终点,#点不能通过,可直接忽略。所有的P为互通的传送门,故可将所以的P看作同一个点。每个能通过的点可以向上下左右四个方向走,如果对应的方向可以通过,则连边,若要走到的点是*,则边权为通过的费用,否则边权为0。
    连边后求Y到C的最短路即可。

    附代码:

    View Code
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    #include <algorithm>
    using namespace std;
    #define V 5005
    #define E 200100
    #define typec int
    int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    const typec inf=0x7FFFFFFF;
    typec cost[E],dist[V];
    char map[V][V];
    int num[V][V];
    int n,m,C,s,t,cou;
    int e,pnt[E],nxt[E],head[V],prev[V],vis[V];
    struct qnode{
        int v;typec c;
        qnode(int vv=0,typec cc=0) :v(vv),c(cc){}
        bool operator<(const qnode& r) const {return c>r.c;}
    };
    void dijkstra(int n,const int src){
        qnode mv;
        int i,j,k,pre;
        priority_queue<qnode> que;
        vis[src]=1;dist[src]=0;
        que.push(qnode(src,0));
        for(pre=src,i=1;i<n;i++){
            for(j=head[pre];j!=-1;j=nxt[j]){
                k=pnt[j];
                if(vis[k]==0 && dist[pre]+cost[j]<dist[k]){
                    dist[k] = dist[pre]+cost[j];
                    que.push(qnode(pnt[j],dist[k]));
                    prev[k]=pre;
                }
            }
            while(!que.empty() && vis[que.top().v]==1)
                que.pop();
            if(que.empty()) break;
            mv = que.top();que.pop();
            vis[pre=mv.v]=1;
        }
    }
    inline void addedge(int u,int v,typec c){
        pnt[e]=v;cost[e]=c;nxt[e]=head[u];head[u]=e++;
    }
    void init(){
        int i,u,v;typec c;
        e=0;
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        memset(prev,-1,sizeof(prev));
        for(i=0;i<=n*m+1;i++) dist[i]=inf;
        cou=1;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                num[i][j]=cou++;
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(map[i][j]=='Y'){
                    s=num[i][j];
                }
                if(map[i][j]=='C'){
                    t=num[i][j];
                }
                if(map[i][j]=='#') continue;
                else if(map[i][j]=='P'){
                    cou--;
                    for(int k=0;k<4;k++){
                        int ii=i+dir[k][0];
                        int jj=j+dir[k][1];
                        if(!(ii>=0 && ii<n && jj>=0 && jj<m)) continue;
                        if(map[ii][jj]=='*'){
                            addedge(0,num[ii][jj],C);
                        }
                        else if(map[ii][jj]=='C'){
                            addedge(0,num[ii][jj],0);
                        }
                        else if(map[ii][jj]=='P'){
                            addedge(0,0,0);
                        }
                    }
                }
                else{
                    for(int k=0;k<4;k++){
                        int ii=i+dir[k][0];
                        int jj=j+dir[k][1];
                        if(!(ii>=0 && ii<n && jj>=0 && jj<m)) continue;
                        if(map[ii][jj]=='*'){
                            addedge(num[i][j],num[ii][jj],C);
                        }
                        else if(map[ii][jj]=='C'){
                            addedge(num[i][j],num[ii][jj],0);
                        }
                        else if(map[ii][jj]=='P'){
                            addedge(num[i][j],0,0);
                        }
                    }
                }
            }
        }
    
    }
    int main(){
        //freopen("in.txt","r",stdin);
        while(scanf("%d%d%d",&n,&m,&C)!=EOF){
            for(int i=0;i<n;i++){
                scanf("%s",map[i]);
            }
            init();
            dijkstra(n*m+1,s);
            if(dist[t]==inf) printf("Damn teoy!\n");
            else printf("%d\n",dist[t]);
        }
        return 0;
    }

    1.未加边界处理,WA了几次。
    2.dijkstra(n,src),点的数量n可以比实际数量多,但至少要为实际数量。

    3.src为起始点,该起始点可以为任一点,不用必须是0点。

    4.堆优化的邻接表dijkstra的时间复杂度为O(E*logE)

  • 相关阅读:
    锋利的jQuery书中推荐的几款插件
    60款很酷的 jQuery 幻灯片演示和下载
    关于viewport
    几个Jquery对话框插件
    从小白白到大白白之初识区块链(如何理解区块链)
    简单的MVC与SQL Server Express LocalDB
    java的MVC与C#
    企业微信登陆方式
    整洁的测试遵循的规则
    Android活动的生命周期
  • 原文地址:https://www.cnblogs.com/markliu/p/2609778.html
Copyright © 2011-2022 走看看