// 384K 0MS G++
#include <cstdio>
#include <cstring>
using namespace std;
int M;
int N;
const int MAX = 11;
// int map[MAX][MAX];
char visitCityFlag[MAX];
char visitRoadFlag[MAX][MAX];
struct Road {
int begin;
int end;
int Ppay;
int Rpay;
int prev;
};
typedef struct Road Road;
// struct LessPay{
// int prev;
// // int begin;
// // int end;
// int pay;
// };
Road roads[MAX];
// typedef struct LessPay LessPay;
// LessPay lessPay[11][11];
#define INF 9999999
int minCost = INF;
int DFS(int begin, int paySum) {
// printf("%d\n", begin);
visitCityFlag[begin]++;
if (begin == N) {
minCost = minCost < paySum ? minCost: paySum;
} else {
for (int i = 0; i <= M; i++) {
if (roads[i].begin == begin && visitCityFlag[roads[i].end] <= 3) {
int curPay = roads[i].Rpay;
if (begin == roads[i].prev ||
visitCityFlag[roads[i].prev]) {
curPay = roads[i].Ppay;
}
DFS(roads[i].end, paySum + curPay);
}
}
}
visitCityFlag[begin]--;
}
void getMin() {
DFS(1, 0);
if (minCost == INF) {
printf("impossible\n");
} else {
printf("%d\n", minCost);
}
}
int main() {
while(scanf("%d %d", &N, &M) != EOF) {
// memset(map, 0xffffffff, sizeof(map)); // -1 means no road
// memset(lessPay, 0, sizeof(lessPay));
memset(visitCityFlag, 0, sizeof(visitCityFlag));
memset(visitRoadFlag, 0, sizeof(visitRoadFlag));
memset(roads, 0, sizeof(roads));
minCost = INF;
int begin;
int end;
int prev;
int Ppay;
int Rpay;
for (int i = 0; i < M; i++) {
scanf("%d %d %d %d %d", &begin, &end, &prev, &Ppay, &Rpay);
// map[begin][end] = Rpay;
roads[i].begin = begin;
roads[i].end = end;
roads[i].prev = prev;
roads[i].Ppay = Ppay;
roads[i].Rpay = Rpay;
// lessPay[begin][end].prev = prev;
// lessPay[begin][end].pay = Ppay;
}
getMin();
}
}
做的没有成就感,因为这道题用DFS做的话,是要用到一种理论性的推倒的,叫"闸数", 知道了这个之后,DFS才显得简单,上面的题解提到了这个。
这道题的难点就在于, 每条路的收费不是固定的,而是取决于之前你是否经过过某个点,如果经过了,那么就会更便宜,这样,按照DFS的思路,每个city只能经过一次的话,是有问题的。例子:
4 5
1 2 1 10 10
2 3 1 30 50
3 4 3 80 80
2 1 2 10 10
1 3 2 10 50
如果 1->2 ->3 ->4 那么需要 10 + 30 + 80 = 120
而这样走: 1->2 ->1 ->3->4则只需要 10 + 10 + 10(没有经过过2的话,是50)+80 = 110,
1->2->1这种回头路在本题可以达成最优解,因此不能简单的在DFS时每个点只能经过一次。
直接用现成的结论(这也是最没成就感的地方),这种情况下,每个city最多经过3次,就能找到最优路径,这样就好办了,
原来的DFSFlag是一个bool,只有访问和没访问过,现在变成了计数器,现在只有这个计数器超过了3才不会对该点继续DFS,
还要注意的是,本题两个点之前不止一条road,因此要用邻接表来表示图,其实因为本题最多只有10条road,因此直接每次遍历全部road匹配起点也可以,时间完全够.