看起来是一道dijkstra题,实际上远没那么简单。dijkstra算法应该属于一种贪心算法,而要想应用贪心算法,就要确保之前的最优解是得到下一个最优解的基础,而这道题里面的条件约束中,路径长度是符合贪心算法的,但是自行车数量就不符合了!
例如
10 5 5 7
0 10 6 5 0
0 1 1
0 2 1
0 3 1
1 4 1
2 4 1
3 4 1
4 5 1
正确答案
0 0->2->4->5 0
若采用dijkstra将得出
4 0->3->4->5 0的错误答案
所以采用DFS回溯,要注意剪枝否则容易超时
#include<stdio.h>
#include<vector>
#define SIZE 505
#define INIFINTE 0x7fffffff
using namespace std;
struct graph{
int dist;
int takeback;
int bringto;
int size;
int path[SIZE];
}cur,res;
int mat[SIZE][SIZE],car[SIZE],cnt;
bool visit[SIZE];
void DFS(int u,int n,int capacity,int aim){
if (u == aim){
if (cur.dist < res.dist)
res = cur;
else if (cur.dist == res.dist){
if (cur.bringto < res.bringto)
res = cur;
else if (cur.bringto == res.bringto){
if (cur.takeback < res.takeback)
res = cur;
}
}
return;
}
for (int i = 1; i <= n;i++)
if (!visit[i] && mat[u][i]){
int tmpdist = cur.dist;
int tmptakeback = cur.takeback;
int tmpbringto = cur.bringto;
cur.dist += mat[u][i];
if (car[i] >= capacity || cur.takeback + car[i] >= capacity){
cur.takeback += car[i] - capacity;
}
else {
cur.bringto += capacity - cur.takeback - car[i];
cur.takeback = 0;
}
visit[i] = true;
cur.path[++cnt] = i;
cur.size++;
DFS(i, n, capacity, aim);
visit[i] = false;
cur.size--;
cnt--;
cur.dist = tmpdist;
cur.bringto = tmpbringto;
cur.takeback = tmptakeback;
}
}
int main(){
freopen("1.in", "r", stdin);
int n, capacity, road, aim;
scanf("%d%d%d%d", &capacity, &n, &aim, &road);
int i;
for (i = 1; i <= n; i++)
scanf("%d", &car[i]);
int from, to, dist;
for (i = 0; i < road; i++){
scanf("%d%d%d", &from, &to, &dist);
mat[from][to] = mat[to][from] = dist;
}
res.bringto = INIFINTE;
res.dist = INIFINTE;
res.takeback = INIFINTE;
cur.path[0] = 0;
DFS(0,n,capacity/2,aim);
printf("%d ", res.bringto);
putchar('0');
for (i = 1; i <= res.size; i++)
printf("->%d", res.path[i]);
printf(" %d\n", res.takeback);
return 0;
}