zoukankan      html  css  js  c++  java
  • 【PAT甲级】1018 Public Bike Management (30 分)(DFS,SPFA)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int inf = 1e9;
    int sum,n,tar,m;
    int num[507];
    int edge[507][507];
    int u,v,val;
    int mn=inf,mn_send=inf,mn_back=inf;
    int cur=0,cur_send=0,cur_back=0;
    int vis[507];
    vector<int>cur_path,ans;
    void dfs(int x){
        if(cur>mn)//已经不是最短路,无需深入了
            return;
        if(x==tar){//到达目标点,有更优解就更新
            if(cur<mn){
                mn=cur;
                mn_send=cur_send;
                mn_back=cur_back;
                ans=cur_path;
            }
            else if(cur==mn&&(cur_send<mn_send||cur_send==mn_send&&cur_back<mn_back)){
                    mn_send=cur_send;
                    mn_back=cur_back;
                    ans=cur_path;
            }
            return;
        }
        for(int i=1;i<=n;++i){
            if(vis[i]||edge[x][i]==inf)//前面已经经过该点或者此路不通就换下一个点
                continue;
            vis[i]=1;
            cur_path.push_back(i);//放进路径中
            cur+=edge[x][i];//修改当前路径长度
            int tmp_send=cur_send;//存放当前需要发出
            int tmp_back=cur_back;//存放当前需要返回
            if(num[i]+cur_back<sum/2)//如果当前站缺车
                cur_send+=sum/2-num[i]-cur_back,cur_back=0;
            else//当前站不缺车
                cur_back+=num[i]-sum/2;
            dfs(i);//在这个点的基础上接着深入
            cur_path.pop_back();//还原到没有经过i点之前的状态
            vis[i]=0;
            cur-=edge[x][i];
            cur_send=tmp_send;
            cur_back=tmp_back;
        }
    }
    int main(){
        std::ios::sync_with_stdio(false);//关闭同步
        cin>>sum>>n>>tar>>m;
        for(int i=0;i<=n;++i)
            for(int j=0;j<=n;++j)
                edge[i][j]=inf,edge[j][i]=inf;//初始化让所有点之间路径无限长
        for(int i=1;i<=n;++i)
            cin>>num[i];
        for(int i=1;i<=m;++i){
            cin>>u>>v>>val;
            edge[u][v]=val;
            edge[v][u]=val;
        }
        dfs(0);//从根节点开始深度优先搜索
        cout<<mn_send<<" 0";
        for(auto&it:ans)
            cout<<"->"<<it;
        cout<<" "<<mn_back;
        return 0;
    }

    /*#include<bits/stdc++.h>
    using namespace std;
    const int maxn = 507;
    const int INF = 1e9;
    typedef struct node{
        int v,l;
    };
    vector<node>adj[maxn];// 邻接表
    int bike[maxn];//存储每个站点现有自行车数
    int c,n,s,m;// 最大容量、站点数、问题站点编号、道路数
    vector<int>pre[maxn];// 前驱结点数组
    int d[maxn];//源点到各点的距离
    int inq[maxn];//是否在队列中
    vector<int>tempPath,path;//路径记录
    int sent=INF,take=INF;// 派送数,回收数
    void SPFA(){// 由于不存在负边,所以无需判断负环(最短路一定存在时可以使用SPFA,效率不错)
        queue<int>q;
        for(int i=1;i<=n;++i)//初始化距离
            d[i]=INF;
        d[0]=0;
        q.push(0);
        inq[0]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            inq[u]=0;
            for(int i=0;i<adj[u].size();++i){
                int v=adj[u][i].v;
                int l=adj[u][i].l;
                if(!v)
                    continue;
                if(d[u]+l<d[v]){//松弛
                    d[v]=d[u]+l;
                    pre[v].clear();//最短距离减小需要先清空前驱结点
                    pre[v].push_back(u);
                    if(!inq[v]){
                        q.push(v);
                        inq[v]=1;
                    }
                }
                else if(d[u]+l==d[v])// 距离相等,只要增加前驱结点
                    pre[v].push_back(u);
            }
        }
    }
    void DFS(int x){
        if(!x){//走回根结点,更新答案
            int remain=0,tempSent=0;//记录处理完第i个站点时多出的自行车数量,和已经派送的自行车数量
            tempPath.push_back(x);
            for(int i=tempPath.size()-2;i>=0;--i){//遍历路径
                int u=tempPath[i];
                remain=remain+bike[u]-c/2;//更新剩余数量
                if(remain<0){//剩余数量小于0
                    tempSent-=remain;//当前站点需要派送
                    remain=0;//剩余数量重置为0
                }
            }
            if(tempSent<sent){//第二优先级,派送数量少
                path=tempPath;
                sent=tempSent;
                take=remain;
            }
            else if(tempSent==sent&&remain<take){//第三优先级,回收数量少
                path=tempPath;
                take=remain;
            }
            tempPath.pop_back();
        }
        tempPath.push_back(x);
        for(int i=0;i<pre[x].size();++i)//处理所有可能的前驱结点
            DFS(pre[x][i]);
        tempPath.pop_back();
    }
    int main(){
        int s1,s2,t;
        scanf("%d%d%d%d",&c,&n,&s,&m);
        for(int i=1;i<=n;++i)
            scanf("%d",&bike[i]);
        for(int i=0;i<m;++i){
            scanf("%d%d%d",&s1,&s2,&t);
            node x;
            x.v=s2;
            x.l=t;
            node y;
            y.v=s1;
            y.l=t;
            adj[s1].push_back(x);
            adj[s2].push_back(y);
        }
        SPFA();
        DFS(s);
        printf("%d ",sent);
        for(int i=path.size()-1;i>=0;--i){
            if(i<path.size()-1)
                printf("->");
            printf("%d",path[i]);
        }
        printf(" %d",take);
        return 0;
    }*/

    //SPFA先处理单源最短路,然后对最短路进行DFS

    保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
  • 相关阅读:
    bzoj1648
    bzoj3404
    bzoj1650
    bzoj1625
    bzoj1606
    bzoj1464
    bzoj1572
    bzoj1617
    bzoj1092
    bzoj1091
  • 原文地址:https://www.cnblogs.com/ldudxy/p/10797655.html
Copyright © 2011-2022 走看看