POJ 3411 Paid Roads

Description

A network of m roads connects N cities (numbered from 1 to N). There may be more than one road connecting one city with another. Some of the roads are paid. There are two ways to pay for travel on a paid road i from city ai to city bi:

  • in advance, in a city ci (which may or may not be the same as ai);
  • after the travel, in the city bi.

The payment is Pi in the first case and Ri in the second case.

Write a program to find a minimal-cost route from the city 1 to the city N.

Input

The first line of the input contains the values of N and m. Each of the following m lines describes one road by specifying the values of ai, bi, ci, Pi, Ri (1 ≤ i m). Adjacent values on the same line are separated by one or more spaces. All values are integers, 1 ≤ m, N ≤ 10, 0 ≤ Pi , Ri ≤ 100, PiRi (1 ≤ i m).

Output

The first and only line of the file must contain the minimal possible cost of a trip from the city 1 to the city N. If the trip is not possible for any reason, the line must contain the word ‘impossible’.

Sample Input

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

Sample Output

110
 
  
解题思路:一开始误以为每条边只能走一次,然后果断用了状压DP来搞这题,结果交的时候WA到死,无奈去POJ看discuss,看有个人的一组数据中表示同一条边可能经过多次,那我的状压DP很显然是错误的。后来网上有人总结每个节点的次数最多能能访问的次数,因此我们完全可以采用dfs来进行搜索即可,给定每个节点限制访问次数为3次,然后在所有可能的路径中选取最小值即可,只到每个节点最多能够访问的次数为3次,那这道题就水到家了,但自己就是想不到,努力刷体提高自己的水平吧。
参考博客:http://blog.youkuaiyun.com/lyy289065406/article/details/6689310
 
  
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <numeric>
#include <utility>
#include <algorithm>
#include <functional>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 110;

struct Edge {
    int a, b, c, p, r, next;
    Edge() { }
    Edge(int t_a, int t_b, int t_c, int t_p, int t_r, int t_next) : a(t_a), b(t_b), c(t_c), p(t_p), r(t_r), next(t_next) { }
}edges[maxn];
int head[20];
int edge_sum;

void init_graph() {
    edge_sum = 0;
    memset(head, -1, sizeof(head));
}

void add_edge(int a, int b, int c, int p, int r) {
    edges[edge_sum].a = a;
    edges[edge_sum].b = b;
    edges[edge_sum].c = c;
    edges[edge_sum].p = p;
    edges[edge_sum].r = r;
    edges[edge_sum].next = head[a];
    head[a] = edge_sum++;
}

int vis[20];
int ans;
int n, m;

void dfs(int u, int cost) {
    if(ans <= cost) return ;
    if(u == n) {
        ans = min(ans, cost);
        return ;
    }
    for(int i = head[u]; i != -1; i = edges[i].next) {
        int v = edges[i].b;
        if(vis[v] < 3) {
            vis[v]++;
            int t = edges[i].r;
            if(vis[edges[i].c]) {
                t = min(t, edges[i].p);
            }
            dfs(v, cost + t);
            vis[v]--;
        }
    }
    return ;
}


int main() {

    //freopen("aa.in", "r", stdin);

    int a, b, c, p, r;
    while(scanf("%d %d", &n, &m) != EOF) {
    init_graph();
    for(int i = 0; i < m; ++i) {
        scanf("%d %d %d %d %d", &a, &b, &c, &p, &r);
        add_edge(a, b, c, p, r);
    }
    ans = inf;
    dfs(1, 0);
    if(ans < inf) {
        printf("%d\n", ans);
    } else {
        printf("impossible\n");
    }
    }
    return 0;
}

/*
struct Edge {
    int a, b, c, p, r;
    Edge() { }
    Edge(int t_a, int t_b, int t_c, int t_p, int t_r) : a(t_a), b(t_b), c(t_c), p(t_p), r(t_r) { }
}E[20];
int dp[(1<<10)+10][15];
int vh[(1<<10)+10];
int n, m;

int main() {

    freopen("aa.in", "r", stdin);

    while(scanf("%d %d", &n, &m) != EOF) {
    for(int i = 0; i < m; ++i) {
        scanf("%d %d %d %d %d", &E[i].a, &E[i].b, &E[i].c, &E[i].p, &E[i].r);
        E[i].a--;
        E[i].b--;
        E[i].c--;
    }
    memset(vh, 0, sizeof(vh));
    for(int i = 0; i < (1<<m); ++i) {
        for(int j = 0; j < m; ++j) {
            if(i&(1<<j)) {
                vh[i] |= (1<<E[j].a);
                vh[i] |= (1<<E[j].b);
            }
        }
    }
    memset(dp, inf, sizeof(dp));
    dp[0][0] = 0;
    for(int i = 1; i < (1<<m); ++i) {
        for(int j = 0; j < n; ++j) {
            if(!(vh[i]&(1<<j))) continue;
            for(int k = 0; k < m; ++k) {
                if(E[k].b == j && (i&(1<<k)) && dp[i^(1<<k)][E[k].a] < inf) {
                    dp[i][j] = min(dp[i][j], dp[i^(1<<k)][E[k].a] + E[k].r);
                    if(vh[i^(1<<k)]&(1<<E[k].c)) {
                        dp[i][j] = min(dp[i][j], dp[i^(1<<k)][E[k].a] + E[k].p);
                    }
                }
            }
        }
    }
    int ans = inf;
    for(int i = 0; i <(1<<m); ++i) {
        ans = min(ans, dp[i][n-1]);
    }
    if(ans < inf) {
        printf("%d\n", ans);
    } else {
        printf("impossible\n");
    }
    }
    return 0;
}
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值