Fishmonger SPOJ - FISHER 有限制的最短路

A fishmonger wants to bring his goods from the port to the market. On his route he has to traverse an area with many tiny city states. Of course he has to pay a toll at each border.

Because he is a good business man, he wants to choose the route in such a way that he has to pay as little money for tolls as possible. On the other hand, he has to be at the market within a certain time, otherwise his fish start to smell.

Input

The first line contains the number of states n and available time t. The first state is the port, the last state is the market. After this line there are n lines with n numbers each, specifying for each state the travel time to the i-th state. This table is terminated with an empty line. The table of the tolls follows in the same format.

n is at least 3 and at most 50. The time available is less than 1000. All numbers are integers.

There are many test cases separated by an empty line. Input terminates with number of states and time equal 0 0.

Output

For each test case your program should print on one line the total amount of tolls followed by the actual travelling time.

Example

Sample input:
4 7
0 5 2 3
5 0 2 3
3 1 0 2
3 3 2 0

0 2 2 7
2 0 1 2
2 2 0 5
7 2 5 0

0 0

Sample output:
6 6

This corresponds to the following situation, the connections are labeled with (time, toll):


图中边为有向边, 每条边的信息有 起点到终点所消耗的时间、金钱。

输出 n, k    节点个数与限制时间。

求在限制时间内最少消耗多少金钱从起点(1)到终点(n)

n~[3,50], time<=1000,

当n k 同时为0时, 输入结束。

1. 节点数据量小 可以考虑DFS

#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ms(x) memset(x, 0, sizeof(x))
using namespace std;
const int N = 52;
int tim[N][N], cost[N][N];
bool vis[N];
int n, k;
int nt, nc;
void dfs(int x, int tpcost, int tptime){
    if(x == n-1){
        if(tpcost < nc ){
            nc = tpcost;
            nt = tptime;
        }
        return;
    }
    for(int i=0;i<n;i++){
        if(vis[i]) continue;
        if(tpcost + cost[x][i]<=nc && tptime + tim[x][i] <= k){
            vis[i] = 1;
            dfs(i, tpcost + cost[x][i],tptime + tim[x][i]);
            vis[i] = 0;
        }
    }
}
int main()
{
    while(scanf("%d%d", &n, &k)!=EOF){
        if(!n && !k) break;
        nt = nc = 0;
        ms(vis);
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                scanf("%d",&tim[i][j]);
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                scanf("%d",&cost[i][j]);
            }
        }
        if(tim[0][n-1]<=k){
            nt = tim[0][n-1];
            nc = cost[0][n-1];
        }
        else {nt = k, nc = inf;}
        vis[0] = 1;
        dfs(0,0,0);
        printf("%d %d\n", nc, nt);
    }
    return 0;
}
2. 最短路变形

将SPFA中的 dist[] vis[] 数组修改成二维的  二维存时间。

跑SPFA时所用队列 存pair

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
#define ms(x) memset(x, 0, sizeof(x))
using namespace std;
const int N = 60;
struct Edge{
    int v, cost;
    Edge(int _v = 0, int _cost = 0):v(_v),cost(_cost){}
};
vector<Edge>E[N];
void addedge(int u, int v, int w){
    E[u].push_back(Edge(v, w));
}
bool vis[N][2005];
int dist[N][2005];
int tim[N][N];
int m;
void SPFA(int st, int n){
    ms(vis);
    memset(dist, inf, sizeof(dist));
    queue<pair<int,int> >que;
    que.push(make_pair(st, 0));
    dist[st][0] = 0;
    while(!que.empty()){
        int u = que.front().first;
        int t = que.front().second;
        vis[u][t] = false;
        que.pop();
        for(int i=0;i<E[u].size();i++){
            int v = E[u][i].v;
            int tptime = t + tim[u][v];
            if(tptime>1000) continue;
            if(dist[v][tptime] > dist[u][t] + E[u][i].cost){
                dist[v][tptime] = dist[u][t] + E[u][i].cost;
                if(!vis[v][tptime]){
                    vis[v][tptime] = true;
                    que.push(make_pair(v, tptime));
                }
            }
        }
    }
    int ans = inf, tim;
    for(int i=0;i<=m;i++){
        if(dist[n-1][i] < ans){
            ans = dist[n-1][i];
            tim = i;
        }
        //printf("%d %d\n",dist[n-1][i], i);
    }
    printf("%d %d\n",ans, tim);
}
int main()
{
    int n;
    while(scanf("%d%d", &n,&m)!=EOF){
        for(int i=0;i<N;i++){
            if(!E[i].empty()) E[i].clear();
        }
        if(!n && !m) break;
        int tpx;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                scanf("%d", &tim[i][j]);
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                scanf("%d", &tpx);
                if(i==j) continue;
                addedge(i, j, tpx);
            }
        }
        SPFA(0, n);
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值