题目说明:有公共自行车网,从原点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;
}