UESTC_酱神的旅行 2015 UESTC Training for Dynamic Programming<Problem M>

M - 酱神的旅行

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)

Submit Status

酱神要去一棵树上旅行。

酱神制定了一个旅行计划,他要按顺序去m个树上的结点,a1,a2,a3,...,am。

酱神有一辆车,树上的每一条边既可以开车通过,也可以走过去,两种方法需要不同的时间。如果选择走路,酱神需要先把车停在结点上,在他下一次要开车的时候,必须先回到停车的结点取车。

酱神和他的爱车一开始都在a1结点上,酱神要依次访问完这m个结点最少需要多少时间。

Input

第一行两个数n,m。

1=<n,m<=5000

接下来n−1行,每行4个数,u,v,walk,drive。表示结点u和结点v之间有一条走路耗时为walk,开车耗时为drive的边。

1=<u,v<=n

1=<walk,drive<=109

最后输入m个数,a1,a2,a3,...,am, 酱神要按顺序访问的结点。

1=<ai<=n

Output

输出一个数,酱神的最小耗时。

Sample input and output

Sample Input Sample Output
2 2
1 2 3 100
1 2
3
4 4
1 2 1 20
3 2 100 1
2 4 1 100
1 2 3 4
23

解题报告:

注意到树上两个点之间的路径是唯一的,且访问点的顺序是固定的,也就是说,经过的点的顺序是固定的,于是我们不妨令

dp(i , j )表示在路径在的第 i 个点,且是否有车的最小花费( 0 -> 无车 , 1 -> 有车 )

dp(cur , 0 ) = min ( dp( cur^1 , 0 ) , dp( cur^1 , 1 ) ) + walk_cost( i -> i + 1) )

è 直接走路过来 / 把车停在上一个点

dp(cur , 1 ) = min ( dp( cur^1 , 1 ) + car_cost(i -> i + 1)  , f[r] + sum[i] )  -> r = a[i]

-> 直接开车过来 / 原来车就停在这,现在回来取(维护走路长度的前缀和)

-> f[r] = min( f[r] , dp(cur , 1) - sum[ cur ^ 1 ] );

注意到本题时限的原因,每次调用无根树转有根树时,需用BFS实现

若需要进一步降低时限,可使用LCA的离线算法,可将复杂度降低至O(N + Q),求路径上的点就不再累述.

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#define pb push_back
typedef long long ll;
const int maxn = 5e3 + 50;
const ll inf = 999999999999999999;
using namespace std;
int n,m,prenode[maxn],cur = 0,h[maxn],passnode[maxn],size,pretarget,target;
ll dp[2][2],f[maxn],sum[2],walkdis[maxn],cardis[maxn];

typedef struct Edge
{
  int target,walk,drive;
  Edge(const int & target, const int & walk , const int & drive)
   {
         this->target = target , this->walk = walk , this->drive = drive;
   }
};

vector<Edge>E[maxn];

typedef struct status
{
   int pos,fat;
};

//无根树转有根树,BFS实现(比递归快 20 % )
inline void init_prenode(int pos)
{
   status q[maxn*2];
   register int front = 0 , rear = 0;
   q[rear].pos = pos , q[rear++].fat = 0 ;
   while(front < rear)
    {
       int thispos = q[front].pos;
       int thisfat = q[front].fat;
       prenode[thispos] = thisfat;
       for(int i = 0 ; i < E[thispos].size() ; ++ i)
        {
           int nextnode = E[thispos][i].target;
           if (nextnode != thisfat)
           {
              if (prenode[nextnode] == thispos) continue; //剪枝
                q[rear].pos = nextnode , q[rear++].fat = thispos;
           }
           else
           walkdis[thisfat] = E[thispos][i].walk , cardis[thisfat] = E[thispos][i].drive;
        }
       ++front;
    }
}

inline void add_nodes()
{
   int k = prenode[pretarget];
   while(k)
    {
          passnode[size++] = k;
          k = prenode[k];
    }
}

int main(int argc,char *argv[])
{
  int st;
  scanf("%d%d",&n,&m);
  for(int i = 0 ; i < n - 1 ; ++ i)
   {
         int a,b,c,d;
         scanf("%d%d%d%d",&a,&b,&c,&d);
         E[a].pb(Edge(b,c,d));
         E[b].pb(Edge(a,c,d));
   }
  for(int i = 1 ; i <= 5000 ; ++ i)
   f[i] = inf;
  memset(dp,0,sizeof(dp));
  memset(sum,0,sizeof(sum));
  memset(prenode,0,sizeof(prenode));
  memset(cardis,0,sizeof(cardis));
  memset(walkdis,0,sizeof(walkdis));
  size = 0;
  dp[cur][0] = inf;
  dp[cur][1] = 0;
  if (m == 1)
   {
         printf("0\n");
         return 0;
   }
  scanf("%d",&pretarget);
  init_prenode(pretarget);
  for(int times = 1 ; times < m ; ++ times)
   {
         scanf("%d",&target);
         size = 0;
         init_prenode(target);
         add_nodes();
         for(int i = 0 ; i < size ; ++ i)
          {
                cur ^= 1;
                int r = passnode[i];
                sum[cur] = sum[cur^1] + walkdis[r];
             dp[cur][0] = min(dp[cur^1][0] , dp[cur^1][1]) + walkdis[r];
             dp[cur][1] =  min( dp[cur^1][1] + cardis[r] , f[r] + sum[cur]);
             f[r] = min(f[r] , dp[cur][1] - sum[cur]);
       }
         pretarget = target;
   }
  printf("%lld\n",min(dp[cur][0],dp[cur][1]));
  return 0;
}
时间: 2024-10-06 00:31:27

UESTC_酱神的旅行 2015 UESTC Training for Dynamic Programming<Problem M>的相关文章

UESTC_酱神赏花 2015 UESTC Training for Dynamic Programming&lt;Problem C&gt;

C - 酱神赏花 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 262143/262143KB (Java/Others) Submit Status 酱神去杭州赏花. 花展在一条街道上举行,这条街道上有一共有n个节点,自左而右从1到n编号,1号和n号是左右两个端点,两个相邻端点之间的距离为1.本次花展一共要展出m朵花,在第ti时刻,有一朵颜值为bi的花将在第ai个节点展出,如果酱神在ti时刻处于第x个节点,那么他能获得的开心值为

UESTC_男神的约会 2015 UESTC Training for Dynamic Programming&lt;Problem J&gt;

J - 男神的约会 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 有一天男神约了学姐姐去看电影,电影院有一个活动,给你一个10*10的矩阵,每一个格子上都有一个0-9的整数,表示一共十种优惠券中的一种. 观众从左上角的格子开始走,走到右下角.每走到一个有着a号优惠券的格子,都必须要玩一个a分钟的游戏来领取这张优惠券. 每次只能向右或向下走.当走到右

UESTC_男神的礼物 2015 UESTC Training for Dynamic Programming&lt;Problem A&gt;

A - 男神的礼物 Time Limit: 3000/3000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status Lweb学长是集训队里公认的男神.有一天他要给美美的学姐姐准备礼物. Lweb学长可是会魔法的哟.为了准备一份礼物,男神要加工n份材料.每一次只能加工相邻的材料. 当男神加工两个魔法值为a,b的材料,男神都要消耗a*b的体力,同时在这个地方合成出魔法值(a+b)%100的材料. 男神

UESTC_邱老师看电影 2015 UESTC Training for Dynamic Programming&lt;Problem F&gt;

F - 邱老师看电影 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 一天邱老师心血来潮想去看电影,但是邱老师的妹子想去逛街,他们谁也没有办法说服对方,于是准备来玩一个游戏来决定听谁的. 邱老师找来w只白鼠和b只黑鼠,邱老师和妹子轮流从袋子里面抓老鼠,谁先抓到白色老鼠谁就赢. 但是有酱神在旁边捣乱,邱老师每抓一只老鼠出来,酱神就偷偷的也从里面抓一只出

UESTC_邱老师选妹子 2015 UESTC Training for Dynamic Programming&lt;Problem H&gt;

H - 邱老师选妹子 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 邱老师长得帅这是人尽皆知,于是追他的妹子就会很多. 但是你知道,邱老师是一个很专一的人,所以他心里面只能有一个人. 于是他决定从追他的众多妹子里挑选一个出来.于是酱神给邱老师出来一个主意,已知有一些妹子,恰好可以给她们从l到r排号,使得每一个妹子有单独的数字,而正好有r-l+1个妹

UESTC_邱老师玩游戏 2015 UESTC Training for Dynamic Programming&lt;Problem G&gt;

G - 邱老师玩游戏 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 邱老师最近在玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中邱老师允许攻克M个城堡并获得里面的宝物. 但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡.你能帮邱老师算出要获得尽量多的宝物应该攻克哪M个城堡吗? In

UESTC_邱老师选妹子(二) 2015 UESTC Training for Dynamic Programming&lt;Problem I&gt;

I - 邱老师选妹子(二) Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 邱老师长得帅这是人尽皆知,于是追他的妹子就会很多.但是你知道,邱老师是一个很专一的人,所以他心里面只能有一个人.于是他决定从追他的众多妹子里挑选一个出来. 在第一轮的选拔中,剩余了一些妹子.酱神又给邱老师出主意了,因为最近酱神刚刚学习了最长上升子序列,所以这次,依然是把妹子们

UESTC_菲波拉契数制 2015 UESTC Training for Dynamic Programming&lt;Problem E&gt;

E - 菲波拉契数制 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 我们定义如下数列为菲波拉契数列: F(1)=1 F(2)=2 F(i)=F(i−1)+F(i−2)(i>=3) 给定任意一个数,我们可以把它表示成若干互不相同的菲波拉契数之和.比如13有三种表示法 13=13 13=5+8 13=2+3+8 现在给你一个数n,请输出把它表示成若干互

UESTC_菲波拉契数制升级版 2015 UESTC Training for Dynamic Programming&lt;Problem L&gt;

L - 菲波拉契数制升级版 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 我们定义如下数列为菲波拉契数列: F(1)=1 F(2)=2 F(i)=F(i−1)+F(i−2)(i>=3) 给定任意一个数,我们可以把它表示成若干互不相同的菲波拉契数之和.比如13有三种表示法 13=13 13=5+8 13=2+3+8 现在给你一个数n,请输出把它表示成