P4568 [JLOI2011]飞行路线 ———— DP思路解法

点击此处进入题目

首先声明 DP解法并不是我想出来的 而是看到题解才明白分层图可以用DP解决 其实好好想一下 Djikstar 的本质无非也就是 BFS + DP ;
后续等我学会了分层图 我也会用分层图的方法来解决这道题目
OK 闲话少叙 先说一下这个题的解题思路

因为Djkstar 堆优化的版本中 存在一个 distance[j] = t.x+ w[i]; 而且是在前者大于后者的条件下 这太像一个DP了 所有我们有了一个非正式 DP的状态转移方程 我们设f[j][k]为 j 点用了k次免费花的最少费用 ;
选第k次花费0的方程为 f[j][k]= f[t.y][k] + w[i];
不选第k次花费为0的方程为 f[j][k] = f[t.y][k - 1];
至此我们得到了一个 伪DP方程 (详细表示还得看代码hh)

Code :

/*
Djikstar 的本质就是BFS + DP;
*/


#include <bits/stdc++.h>

#define x first
#define y second
#define PII pair<int,int>

using namespace std;

const int M = 100010;

int f[M][15];
bool st[M];
int n,m,p,s,t;

int e[M],w[M],ne[M],h[M],idx ;

priority_queue<PII,vector<PII>,greater<PII> > q;

void add(int a ,int b ,int c)
{
    e[idx] = b, ne[idx] = h[a] , w[idx] = c , h[a] = idx ++;
}

void Djikstar()
{
    for(int i = 0 ; i <= p ; i ++) f[s][i] = 0;
    
    for(int k = 0 ; k <= p; k ++)
    {
          memset(st,0,sizeof st);
          q.push({0,s});
          
          while(q.size())
          {
              PII t = q.top(); q.pop();
              
              if(st[t.y]) continue;
              st[t.y] = true;
              
              for(int i = h[t.y] ; i != -1 ; i = ne[i])
              {
                    
                  bool is = false;
                  int j = e[i];
                  
                  if(k && f[j][k] > f[t.y][k -1])
                  {
                      f[j][k] = f[t.y][k - 1] ;
                      is = true;
                  }
                  if(f[j][k] > f[t.y][k] + w[i]) f[j][k] = f[t.y][k] + w[i] , is = true;
                  
                  if(is) q.push({f[j][k] , j});
              }
          }
    }
}

int main()
{
    memset(h,-1,sizeof h);
    memset(f,0x3f,M * 15);
    cin >> n >> m >> p >> s >> t;
    
    for(int i = 1 ; i <= m; i ++)
    {
        int x,y,z;
        cin >> x >> y >> z;
        add(x,y,z);
        add(y,x,z);
    }  
    Djikstar();
    
    cout << f[t][p] << endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值