If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.
因上述两个要求,光用贪心的dijkstra是不正确的。
1. dijkstra求最短路
2. dfs求出符合上述要求的路径。这个比较花心思。
3. 测试点9可能超时,需要在深搜时剪枝
dist + map[now.back()][i] <= dis[sp]
4. 注意到N是500.. 之前数组开成100了 —— 测试点9是大数据测试
5. 测试用例附在代码后面
代码:
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <list>
using namespace std;
const int INF = 2100000000;
int map[505][505];
int cmax, n, sp, m;
int has[505], dis[505], ans1, ans2;
bool vi[505];
list<int> path, tmp;
void init()
{
scanf("%d%d%d%d", &cmax, &n, &sp, &m);
for (int i = 1; i <= n; ++ i)
{
scanf("%d", has + i);
dis[i] = INF;
}
for (int i = 0; i <= n; ++ i)
{
for (int j = 0; j <= n; ++ j)
{
map[i][j] = map[j][i] = INF;
}
}
ans1 = ans2 = INF;
while (m --)
{
int x, y, dis;
scanf("%d%d%d", &x, &y, &dis);
map[x][y] = map[y][x] = dis;
}
}
void dijkstra()
{
memset(vi, 0, sizeof(vi));
dis[0] = 0;
for (int i = 0; i <= n; ++ i)
{
int v = -1, minn = INF;
for (int j = 0; j <= n; ++ j)
{
if (dis[j] < minn && vi[j] == false)
{
v = j;
minn = dis[j];
}
}
if (v == -1)
{
break;
}
vi[v] = true;
for (int j = 1; j <= n; ++ j)
{
if (dis[j] > dis[v] + map[v][j])
{
dis[j] = dis[v] + map[v][j];
}
}
}
}
bool not_in(int city, list<int>& now)
{
for (auto it = now.begin(); it != now.end(); ++ it)
{
if (*it == city)
{
return false;
}
}
return true;
}
void dfs(list<int>& now, int dist)
{
if (now.empty() == true)
{
for (int i = 1; i <= n; ++ i)
{
if (map[0][i] <= dis[sp])
{
now.push_back(i);
dfs(now, dist + map[0][i]);
now.pop_back();
}
}
return ;
}
if (now.back() == sp)
{
// printf("lookat here\n");
int send_from = 0, take_back = 0;
for (auto it = now.begin(); it != now.end(); ++ it)
{
if (cmax/2 - has[*it] > take_back)
{
send_from += cmax/2 - has[*it] - take_back;
take_back = 0;
} else if (cmax/2 - has[*it] > 0 && cmax/2 - has[*it] <= take_back)
{
take_back -= cmax/2 - has[*it];
} else if (cmax/2 - has[*it] <= 0)
{
take_back -= cmax/2 - has[*it]; // 其实是加上了一些车
}
}
if (ans1 > 0 && send_from < ans1)
{
ans1 = send_from;
ans2 = take_back;
path = now;
} if (ans1 == send_from && take_back < ans2)
{
// ans1 = send_from;
ans2 = take_back;
path = now;
}
return ;
}
for (int i = 1; i <= n; ++ i)
{
if (map[now.back()][i] != INF
&& dist + map[now.back()][i] <= dis[sp]
&& not_in(i, now))
{
int v = now.back();
now.push_back(i);
dfs(now, dist + map[v][i]);
now.pop_back();
}
}
}
void print()
{
printf("%d 0", ans1);
for (auto it = path.begin(); it != path.end(); ++ it)
{
printf("->%d", *it);
}
printf(" %d\n", ans2);
}
int main()
{
init();
dijkstra();
dfs(tmp, 0);
print();
return 0;
}
测试用例:
10 3 3 3
6 7 0
0 1 1
0 2 1
0 3 3
10 3 3 3
6 7 9
0 1 1
0 2 1
0 3 3
10 5 5 6
8 7 0 0 5
0 1 1
0 2 1
1 3 1
2 4 1
3 5 1
4 5 1
10 5 5 6
3 4 7 6 5
0 1 1
0 2 1
1 3 1
2 4 1
3 5 1
4 5 1