zoukankan      html  css  js  c++  java
  • SPFA 上手题 数 枚:

    1, HDU 1548 A strange lift :http://acm.hdu.edu.cn/showproblem.php?pid=1548

    这道题可以灰常巧妙的转换为一道最短路题目,对第i层,按钮数字为button[i],则如果满足相加<=N,则把i到i+button[i]的路径长度设为1(巧妙将按钮次数转换为路径长度),同理,相减如果满足>=1,则把i到i-button[i]的路径长度设为1.则最后输出终点的最短路的长度即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    
    const int INF=0x3f3f3f3f;
    
    int n,a,b;
    int map[210][210],vis[210],dis[210];
    
    int SPFA(){
        for(int i=1;i<=n;i++){
            dis[i]=INF;
            vis[i]=0;
        }
        queue<int> q;
        while(!q.empty())
            q.pop();
        dis[a]=0;
        vis[a]=1;
        q.push(a);
        while(!q.empty()){
            int cur=q.front();
            q.pop();
            vis[cur]=0;
            for(int i=1;i<=n;i++)
                if(dis[i]>dis[cur]+map[cur][i]){
                    dis[i]=dis[cur]+map[cur][i];
                    if(!vis[i]){
                        vis[i]=1;
                        q.push(i);
                    }
                }
        }
        return dis[b];
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        while(~scanf("%d",&n) && n){
            scanf("%d%d",&a,&b);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    map[i][j]=INF;
            int x;
            for(int i=1;i<=n;i++){
                scanf("%d",&x);
                if(i-x>=1)
                    map[i][i-x]=1;
                if(i+x<=n)
                    map[i][i+x]=1;
            }
            int ans=SPFA();
            if(ans==INF)
                ans=-1;
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    另附BFS解法:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    
    int n,a,b;
    int k[210],vis[210];
    
    struct node{
        int x,step;
    };
    
    int BFS(){
        queue<node> q;
        while(!q.empty())
            q.pop();
        node cur,next;
        cur.x=a,    cur.step=0;
        vis[cur.x]=1;
        q.push(cur);
        while(!q.empty()){
            cur=q.front();
            q.pop();
            if(cur.x==b)
                return cur.step;
            next.x=cur.x-k[cur.x];
            next.step=cur.step+1;
            if(next.x>=1 && next.x<=n && !vis[next.x]){
                vis[next.x]=1;
                q.push(next);
            }
            next.x=cur.x+k[cur.x];
            if(next.x>=1 && next.x<=n && !vis[next.x]){
                vis[next.x]=1;
                q.push(next);
            }
        }
        return -1;
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        while(~scanf("%d",&n) && n){
            scanf("%d%d",&a,&b);
            for(int i=1;i<=n;i++)
                scanf("%d",&k[i]);
            memset(vis,0,sizeof(vis));
            int ans=BFS();
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    2,  HDU 3790 最短路径问题 : http://acm.hdu.edu.cn/showproblem.php?pid=3790

    二维距离(路程,价格),优先判断路程…

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    
    const int VM=1010;
    const int EM=100010;
    const int INF=0x3f3f3f3f;
    
    struct Edge{
        int to,nxt;
        int cap,cost;
    }edge[EM<<1];
    
    int n,m,cnt,head[VM];
    int src,des,dis[VM],pay[VM],vis[VM];
    
    void addedge(int cu,int cv,int cw,int cc){
        edge[cnt].to=cv;    edge[cnt].cap=cw;   edge[cnt].cost=cc;
        edge[cnt].nxt=head[cu];     head[cu]=cnt++;
    }
    
    void SPFA(){
        for(int i=1;i<=n;i++){
            dis[i]=INF;
            pay[i]=INF;
            vis[i]=0;
        }
        queue<int> q;
        while(!q.empty())
            q.pop();
        dis[src]=0;
        pay[src]=0;
        vis[src]=1;
        q.push(src);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=edge[i].nxt){
                int v=edge[i].to;
                if(dis[v]>dis[u]+edge[i].cap || (dis[v]==dis[u]+edge[i].cap && pay[v]>pay[u]+edge[i].cost)){    //二维距离(路程,价格),优先判断路程…
                    dis[v]=dis[u]+edge[i].cap;
                    pay[v]=pay[u]+edge[i].cost;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        while(~scanf("%d%d",&n,&m)){
            if(n==0 && m==0)
                break;
            cnt=0;
            memset(head,-1,sizeof(head));
            int u,v,d,p;
            while(m--){
                scanf("%d%d%d%d",&u,&v,&d,&p);
                addedge(u,v,d,p);   //因为是无向边,所以建双向图
                addedge(v,u,d,p);
            }
            scanf("%d%d",&src,&des);
            SPFA();
            printf("%d %d
    ",dis[des],pay[des]);
        }
        return 0;
    }
    View Code

    3, HDU  2066  一个人的旅行 : http://acm.hdu.edu.cn/showproblem.php?pid=2066

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    
    using namespace std;
    
    const int INF=0x3f3f3f3f;
    
    struct Edge{
        int to,nxt;
        int cap;
    }edge[100010];
    
    int T,S,D;
    int cnt,head[1100];
    int src,des,dis[1100],vis[1100];
    
    void addedge(int cu,int cv,int cw){
        edge[cnt].to=cv;    edge[cnt].cap=cw;   edge[cnt].nxt=head[cu];
        head[cu]=cnt++;
    }
    
    int SPFA(){
        queue<int> q;
        while(!q.empty())
            q.pop();
        for(int i=0;i<=1001;i++){
            dis[i]=INF;
            vis[i]=0;
        }
        dis[src]=0;
        vis[src]=1;
        q.push(src);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=edge[i].nxt){
                int v=edge[i].to;
                if(dis[v]>dis[u]+edge[i].cap){
                    dis[v]=dis[u]+edge[i].cap;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        return dis[des];
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        while(~scanf("%d%d%d",&T,&S,&D)){
            cnt=0;
            memset(head,-1,sizeof(head));
            int u,v,w;
            while(T--){
                scanf("%d%d%d",&u,&v,&w);
                addedge(u,v,w);
                addedge(v,u,w);
            }
            src=0,  des=1001;
            while(S--){
                scanf("%d",&v);
                addedge(src,v,0);
            }
            while(D--){
                scanf("%d",&u);
                addedge(u,des,0);
            }
            int ans=SPFA();
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    4, HDU  2112  HDU Today : http://acm.hdu.edu.cn/showproblem.php?pid=2112

    trick:起点和终点有可能是同一点,坑爹呐。。。。。。。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<map>
    #include<queue>
    
    using namespace std;
    
    const int N=100010;
    const int INF=0x3f3f3f3f;
    
    struct Edge{
        int to,nxt;
        int cap;
    }edge[N<<1];
    
    int all,cnt,head[N];
    int src,des,dis[N],vis[N];
    
    void addedge(int cu,int cv,int cw){
        edge[cnt].to=cv;    edge[cnt].cap=cw;   edge[cnt].nxt=head[cu];
        head[cu]=cnt++;
    }
    
    int SPFA(){
        queue<int> q;
        while(!q.empty())
            q.pop();
        for(int i=0;i<=all;i++){
            dis[i]=INF;
            vis[i]=0;
        }
        dis[src]=0;
        vis[src]=1;
        q.push(src);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=edge[i].nxt){
                int v=edge[i].to;
                if(dis[v]>dis[u]+edge[i].cap){
                    dis[v]=dis[u]+edge[i].cap;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        return dis[des];
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        int n;
        char str1[40],str2[40];
        char s[40],t[40];
        map<string,int> mp;
        while(~scanf("%d",&n) && n!=-1){
            cnt=0;
            memset(head,-1,sizeof(head));
            all=1;
            mp.clear();
            scanf("%s%s",s,t);
            mp[s]=all++;    //起点和终点有可能是同一点
            src=mp[s];
            if(mp[t]==0)
                mp[t]=all++;
            des=mp[t];
            int w;
            while(n--){
                scanf("%s%s%d",str1,str2,&w);
                if(mp[str1]==0)
                    mp[str1]=all++;
                if(mp[str2]==0)
                    mp[str2]=all++;
                addedge(mp[str1],mp[str2],w);
                addedge(mp[str2],mp[str1],w);
            }
            int ans=SPFA();
            if(ans==INF)
                ans=-1;
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    网页中加入Flash的代码
    AJAX示例
    图片过滤效果
    ASP.NET性能优化
    什么是AJAX
    动态获取enum的值并且添到List中
    VSTO为Excel快捷菜单添加项
    OpenXML for office SDK 2.5 Download url.
    WebClient
    C#监控本地目录文件变化
  • 原文地址:https://www.cnblogs.com/jackge/p/3164300.html
Copyright © 2011-2022 走看看