1018. Public Bike Management (30)

来源:互联网 发布:苹果版解压缩软件 编辑:程序博客网 时间:2024/06/15 21:26

题目说明:有公共自行车网,从原点0出发到目标点sp,要把所有点的自行车数都置为half-full,找到最优路径,优先级依次为:路径长度最短,send最少,back最少。

思路:最短路加dfs求最优解

我先附上过了的代码,这是我在错误的思路上做了好久没全对最后妥协查了题解的代码

#include<bits/stdc++.h>using namespace std;const int M = 501;const int INF = 0x3f3f3f3f;int maxn;int m,n,E;int cost[M];vector<int> pre[M];int e[M][M];int own[M];int used[M];int limit;void dijkstra(int s){    memset(used,0,sizeof(used));    for(int i = 0;i <= n;i++)cost[i] = INF;    for(int i = 0; i <= n; i++)    {        if(e[s][i] != INF)        {            cost[i] = e[s][i];            pre[i].push_back(s);        }    }    int u = s;    used[u] = 1;    while(true)    {        int v;        int minn = INF;        bool ok = false;        for(int i = 0; i <= n; i++)        {            if(!used[i]&&cost[i] < minn)            {                minn = cost[i];                v = i;                ok = true;            }        }        if(!ok)            return ;        u = v;        used[u] = 1;        for(int i = 0; i <= n; i++)        {            if(!used[i]&&cost[i] > cost[u] + e[u][i])            {                cost[i] = cost[u] + e[u][i];                pre[i].clear();                pre[i].push_back(u);            }            else if(!used[i]&&cost[i] == cost[u] + e[u][i])            {                pre[i].push_back(u);            }        }    }}vector<int> p;int fs = INF;int fr = INF;void dfs(int id,int cr,int cs,vector<int> path){    //printf("%d %d %d\n",id,cr,cs);    if(id == E)    {        if(cs < fs||(cs == fs&&cr < fr))        {            fr = cr;            fs = cs;            p = path;        }    }    else    {        for(int i = 0;i < pre[id].size();i++)        {            int v = pre[id][i];            //cout << id << " " << v <<endl;            int tmp = own[v] - limit;            int ts,tr;            if(cr + tmp >= 0)            {                ts = cs;                tr = cr + tmp;            }            else            {                ts = cs - cr - tmp;                tr = 0;            }            path.push_back(v);            dfs(v,tr,ts,path);            path.pop_back();        }    }}int main(){    scanf("%d%d%d%d",&maxn,&n,&E,&m);    limit = maxn/2;    for(int i = 1; i <= n; i++)        scanf("%d",&own[i]);    for(int i = 0; i <= n; i++)        for(int j = 0; j <= n; j++)            if(i != j)                e[i][j] = INF;    for(int i = 1; i <= m; i++)    {        int a,b,c;        scanf("%d%d%d",&a,&b,&c);        e[a][b] = e[b][a] = c;    }    dijkstra(E);    p.clear();    p.push_back(0);    dfs(0,0,0,p);    int l = p.size();    printf("%d %d",fs,p[0]);    for(int i = 1;i < p.size();i++)    {        printf("->%d",p[i]);    }    printf(" %d\n",fr);    return 0;}
这个题我开始没有认真读题,误以为局部最优就是最优解,眼瞎没有看见最短路径之间这个条件,然后我就在dijstra上做文章,以至于好久都没有过,就是有一组过不去,真的是气哭,前期的时候也是因为有个数组忘了初始化,导致一错错了一半,好在这个不是大问题。

以下的代码是dijstra+贪心:

#include<bits/stdc++.h>using namespace std;const int M = 501;const int INF = 0x3f3f3f3f;int maxn;int m,n,E;int cost[M];int pre[M];int send[M];int ret[M];int e[M][M];int own[M];int used[M];int limit;void dijkstra(int s){    memset(used,0,sizeof(used));    for(int i = 0;i <= n;i++) cost[i] = INF;    for(int i = 1; i <= n; i++)    {        if(e[s][i] != INF)        {            cost[i] = e[s][i];            pre[i] = s;            int tmp = limit - own[i];            if(tmp >= 0)            {                send[i] = tmp;                ret[i] = 0;            }            else            {                send[i] = 0;                ret[i] = -tmp;            }        }    }    int u = s;    used[u] = 1;    while(true)    {        int v;        int minn = INF;        bool ok = false;        for(int i = 1; i <= n; i++)        {            if(!used[i]&&cost[i] < minn)            {                minn = cost[i];                v = i;                ok = true;            }        }        if(!ok)            return ;        u = v;        used[u] = 1;        for(int i = 1; i <= n; i++)        {            if(!used[i]&&cost[i] > cost[u] + e[u][i])            {                cost[i] = cost[u] + e[u][i];                int tmp = own[i] - limit;                if(ret[u] + tmp >= 0)                {                    ret[i] = ret[u] + tmp;                    send[i] = send[u];                }                else                {                    send[i] = send[u] - ret[u] - tmp;                    ret[i] = 0;                }                pre[i] = u;            }            else if(!used[i]&&cost[i] == cost[u] + e[u][i])            {                int tmp = own[i] - limit;                int ts,tr;                if(ret[u] + tmp >= 0)                {                    ts = send[u];                    tr = ret[u] + tmp;                }                else                {                    tr = 0;                    ts = send[u] - tmp - ret[u];                }                if(ts < send[i])                {                    ret[i] = tr;                    send[i] = ts;                    pre[i] = u;                }                else if(ts == send[i]&&tr < ret[i])                {                    ret[i] = tr;                    pre[i] = u;                }            }        }    }}int main(){    scanf("%d%d%d%d",&maxn,&n,&E,&m);    limit = maxn/2;    for(int i = 1; i <= n; i++)        scanf("%d",&own[i]);    for(int i = 0; i <= n; i++)        for(int j = 0; j <= n; j++)                e[i][j] = INF;    for(int i = 1; i <= m; i++)    {        int a,b,c;        scanf("%d%d%d",&a,&b,&c);        e[a][b] = e[b][a] = c;    }    for(int i = 1;i <= n;i++)    {        send[i] = ret[i] = INF;    }    dijkstra(0);    vector<int> p;    int u = E;    while(u!=0)    {        p.push_back(u);        u = pre[u];    }    p.push_back(0);    int l = p.size();    printf("%d %d",send[E],p[l-1]);    for(int i = l-2;i >= 0;i--)    {        printf("->%d",p[i]);    }    printf(" %d\n",ret[E]);    return 0;}




原创粉丝点击