UPC ——9301: CHEAP DELIVERIES(K次最短路dijktra+状压DP)

9301: CHEAP DELIVERIES

 

题目传送门

时间限制: 1 Sec  内存限制: 128 MB
提交: 190  解决: 52
[提交] [状态] [讨论版] [命题人:admin]

 

题目描述

Abu runs a delivery service where he deliver items from one city to another. As with any business, Abu wants to decrease his cost as much as possible. The further he travel, the more fuel he will use. 
In any particular day, Abu have k items to deliver. Each item needs to be delivered from a start city  to  a  destination  city.  Each  city  is  represented  by  an  integer.  Because  of  his  business policies, he can only deliver one item at a time. However, he can deliver the items in any order that he wants, as long as he deliver all of them. So, everyday he starts at an item's start city and deliver the item to its destination city. Then, he goes to the next items's start city and deliver the item to the its destination city. And, he does this until he does not have any item left to deliver. 
From experimentation, Abu notices that the distance he travels change if he change the order of his delivery. He thought, he can save a lot of money if he knows the best delivery order. He knows that you are very good at solving this kind of problem. So he wants you to solve it for him. Given a list of cities, a list of roads between the cities (and the road's length), and a description of deliveries he must do, determine what is the minimum total travel distance, given that he execute his delivery in the most efficient order. Every road is bidirectional and there can be more than one road between two cities. Abu can use any road as many time as he wants. 

 

输入

The first line consists of two integer n, m, k (2 ≤ n, m ≤ 104 ), (1 ≤ k ≤ 18) which is the number of cities, the number of roads and the number of items respectively. 
The next m line each consist of 3 integers, ui , v i , l i  (1 ≤ ui , vi  ≤ 104 ), (1 ≤ li  ≤ 106 ), which denotes that a road exists from city ui  to vi  with length li . 
The next k line each consist of 2 integers, fi , di  (1 ≤ fi , di  ≤ 104 ) which denotes that the ith item is from city fi  and its destination is city di . 

 

输出

A single integer, which is the minimum total travel distance given that Abu deliver all items optimally, or -1 if its is impossible for him to deliver all items. 

 

样例输入

5 5 3 
1 2 1 
2 3 2 
3 4 3 
4 5 4 
5 2 4 
2 3 
1 2 
5 3

 

样例输出

12

 

来源/分类

ICPC 2018 Malaysia 

 

解题思路:

因为目的是求(1)从S[i] 出发到F[i] 然后 再去到下一个S[i] 重复过程(1)直到去到最后一个F[i] 。任意走一次该过程,会发现总路径可认为是从最后的F[i]到其S[i]再从S[i]出发寻找最短的一条S[i]到F[j]的路,所以,下一个F[j]的选择就会直接影响总的路程,并且是唯一影响答案的因素。 

 

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = (int)1e4 +5;
const int INF = 10000000000LL;    
int n,m,k; 
vector <pair<int,int> > mp[maxn];   
pair<int,int> pi[20]; 
int d[20][20]; 
int dis[maxn]; 
ll dp[1<<18][20];
int vis[maxn];
priority_queue <pair<int,int> > Q;     
 
void init()
{
    for(int i=1;i<=n;i++)
        dis[i] = INF;
    memset(vis,0,sizeof(vis));
}
void dij(int s) 
{
    init();
    while(!Q.empty()) Q.pop();
    dis[s] = 0;//鑷繁鍒拌嚜宸?
    Q.push(make_pair(0,s)); 
    while(!Q.empty() ) 
    {
        int cur = Q.top().second;
        Q.pop();
        if(vis[cur]) continue;
        vis[cur] = 1; 
        for(int i=0;i<mp[cur].size();i++)
        {
            int next = mp[cur][i].first;
            if(!vis[next] && dis[next] > dis[cur] + mp[cur][i].second) 
             {
                 dis[next] = dis[cur] + mp[cur][i].second;  
                 Q.push(make_pair(-dis[next],next));   
             }
        }
    }
 
}
 
int main(void)
{
    std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); 
    cin>>n>>m>>k;
    while(m--)
    {
        int u,v,w;
        cin>>u>>v>>w;
        mp[u].push_back(make_pair(v,w)) ;
        mp[v].push_back(make_pair(u,w)) ;
    }
    for(int i=1;i<=k;i++)  
        cin>>pi[i].first>>pi[i].second;
 
     
    for(int i = 0;i < 20;i++)
        for(int j = 0;j < 20;j++)
                d[i][j] = INF;
                 
                 
    for(int i=1;i<=k;i++)
    {
        dij(pi[i].first);
        for(int j=1;j<=k;j++) 
        {
            d[i][j] = dis[pi[j].second]; 
        }
    }
     
    for(int i = 0;i< (1<<k); i++) 
          for(int j=0;j<=k;j++) 
                dp[i][j] = INF; 
    for(int i=0;i<k ; i++) dp[1<<i][i] = d[i+1][i+1];   
     
     
    ll ans = INF;
    for(int i=1; i<(1<<k) ; i++)
    {
 
        for(int j=0;j<k;j++)   
        {
            if(!( i&(1<<j) ))   continue;
            for(int q=0;q<k;q++)
            {
                if( i & (1 << q) )continue; 
                       
                dp[i|(1<<q)][q] = min(dp[i|(1<<q)][q] , dp[i][j] + d[j+1][q+1] + d[q+1][q+1]) ;    
                if((i|(1<<q)) + 1 == (1<<k)) 
                {
                    ans = min(ans, dp[(i|(1<<q))][q]);
                 //    cout<<"dp: "<<dp[i|(1<<q)][q] <<endl;
                }
            }
           //if( i + 1 == (1<<k) ) ans = min(ans,dp[i][j]);  
 
        }
    }
    //printf("%lld\n",ans == INF? -1:ans);  
    cout<<(ans == INF ? -1:ans)<<endl; 
 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值