POJ 3414 Paid Roads(状态压缩最短路)

题意:

求一条从1-N的最短路,当从点a到点b时有两个选择:

1.直接走过a, b, 消耗路费r

2.从a到b,当且仅当c也走过,在c处付路费min(p, r)

所以需要记录已经走过的顶点,判断是否需要在c处提前付路费

限制:

1 ≤ m, N ≤ 10,

0 ≤ Pi , Ri ≤ 100,

PiRi (1 ≤ i m).

/***********************************************
 * Author: fisty
 * Created Time: 2015-08-05 17:46:53
 * File Name   : poj3411.cpp
 *********************************************** */
#include <iostream>
#include <cstring>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
#define Memset(x, a) memset(x, a, sizeof(x))
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair<int, int> P;
#define FOR(i, a, b) for(int i = a;i < b; i++)
#define lson l, m, k<<1
#define rson m+1, r, k<<1|1
#define MAX_N 11
int n, m;
struct Rode{    
    int b, c, p, r;
    Rode(int b, int c, int p, int r):b(b), c(c), p(p), r(r)
    {}
};
struct State{
    int u, cost, coverd;
    State(int u, int cost, int coverd):u(u), cost(cost), coverd(coverd)
    {}
    bool operator < (const State& e1) const {
        return e1.cost < cost;
    }   
};
vector<Rode> G[MAX_N];
priority_queue <State> que;
int used[MAX_N][1<<MAX_N];
void solve(){
    Memset(used, 0);
    que.push(State(1, 0, 1<<1)); //开始顶点为1,花费为0,走过顶点1
    State result(-1,-1,-1);
    while(que.size()){
        State q = que.top(); que.pop();
        if(used[q.u][q.coverd]) continue;
        used[q.u][q.coverd] = 1;
        if(q.u == n){
            result = q;
            break;
        }
        vector<Rode>::iterator it;
        for(it = G[q.u].begin(); it != G[q.u].end(); ++it){
            Rode e = *it;
            int cost = q.cost;
            if(q.coverd & (1 << e.c)){
                cost += min(e.p, e.r);
            }else{
                cost += e.r;
            }
            que.push(State(e.b, cost , q.coverd|(1<<e.b)));
        }
    }
    if(result.u == -1){
        printf("impossible\n");
    }else{
        printf("%d\n", result.cost);
    }
}
int main() {
    //freopen("in.cpp", "r", stdin);
    //cin.tie(0);
    //ios::sync_with_stdio(false);
    while(~scanf("%d%d", &n, &m)){
        int a, b, c, p, r;
        for(int i = 0;i < m; i++){
            scanf("%d%d%d%d%d", &a, &b, &c, &p, &r);
            G[a].push_back(Rode(b, c, p, r));
        }
        solve();
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值