zoukankan      html  css  js  c++  java
  • 2012 MultiUniversity Training Contest 1

    仅仅做出了1009(hdu-4308),广搜,搜到第一个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;
    }

    未加边界处理,WA了几次,o(╯□╰)o,以后做棋盘上的题一定一定要注意边界处理。

    在下一场比赛到来之前,要懂得:

    4.2-SAT过1007(8.20)

    6.最大流过1010(8.21)

    3.生成树计数过1006(8.22)

    2.线段树过1003(8.23)

    5.最短路过1009(8.24)

    1.KMP过1001(8.25)

  • 相关阅读:
    结对四则运算04—网页版
    每周总结07
    每周总结06
    求循环数组中最大子数组的和
    每周总结05
    每周总结03
    每周总结04
    四则运算03
    开发过程记录
    Ubuntu下安装mysql和可视化工具超级简单教程
  • 原文地址:https://www.cnblogs.com/markliu/p/2600097.html
Copyright © 2011-2022 走看看