poj-3411

来源:互联网 发布:淘宝怎么看行业分析 编辑:程序博客网 时间:2024/06/07 19:07
// 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 9999999int 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();    }}

http://blog.csdn.net/lyy289065406/article/details/6689310

做的没有成就感,因为这道题用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匹配起点也可以,时间完全够.

0 0
原创粉丝点击