0
点赞
收藏
分享

微信扫一扫

poj-3411


// 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匹配起点也可以,时间完全够.

举报

相关推荐

0 条评论