这个题目我昨晚看到的,没什么思路,因为马里奥有boot加速器,只要中间没有城堡,即可不耗时间和脚力,瞬间移动不超过L距离,遇见城堡就要停下来,当然不能该使用超过K次。。。我纠结了很久,最终觉得还是只能写个BFS,剪了下枝,不出意料还是TLE。。。

后来还是找的别人博客看了一下。。。其实之前也做了好多DP,也应该能想到,既然加速器可以用k次,则,每个点都有k个状态,通过DP,把各个状态进行下取优,就可以了。。。

这不得不让我对DP有了些新的理解,DP在状态转移的时候,就好像最短路里面的松弛操作,或者二者只是外表的不同,本质是遵循一个道理。

当然在DP之前还需要一些处理

首先用个g[][]二维数组把题目所给的路径给存下来,再用Floyd把点到点的最短路先求出来,当然不是完全的Floyd,因为这个floyd求出来的最短路完全是为了之后用加速器,加速器不允许途中有城堡,因此在floyd的时候要加判断条件,有城堡在中间就不走。

用一个d[i][k]表示i点在加速器使用了k次的最短路径。

一开始还以为是总加速距离不能超过L,后来发现原来是每次。要细心

#include <iostream>
#include <cstdio>
#include <cstring>
#define N 110
#define INF 1<<29
using namespace std;
int A,B,M,L,K;
int g[N][N],d[N][];
int q[N*],st[N*],inq[N][];
void init()
{
for (int i=;i<=A+B;i++)
{
for (int j=;j<=A+B;j++)
{
if (i==j){
g[i][j]=;
}
else
g[i][j]=INF;
}
}
}
void floyd()
{
int i,j,k;
for (k=;k<=A+B;k++)
{
for (i=;i<=A+B;i++)
{
for (j=;j<=A+B;j++)
{
if (k>A) continue;//Floyd 只求能用加速器飞越的最短路
if (g[i][j]>g[i][k]+g[k][j])
g[i][j]=g[i][k]+g[k][j];
//cout<<g[i][j]<<" "<<i<<" "<<j<<endl;
}
}
}
}
void solve()
{
int maxn=(K+)*(A+B);
int front=,rear=;
memset(inq,,sizeof inq);
for (int i=;i<=A+B;i++)
{
for (int j=;j<=K;j++)
{
d[i][j]=INF;
//cout<<d[i][j]<<endl;
}
}
d[A+B][]=; //初始状态
q[rear]=A+B; //这次尝试了一下手动队列,而不是STL队列,效果相同,不过手工的队列时间应该好一些。
st[rear]=;
rear++;
while (front!=rear)
{
int u=q[front];
int k=st[front];
front++;
if (front>maxn)
front=;
inq[u][k]=;
// cout<<u<<" "<<k<<" "<<d[u][k]<<endl;
for (int i=;i<=A+B;i++)
{
if (d[i][k]>d[u][k]+g[u][i]) //进行普通最短路,保存当前状态
{
d[i][k]=d[u][k]+g[u][i];
if (!inq[i][k])
{
q[rear]=i;
st[rear]=k;
rear++;
if (rear>maxn)
rear=;
inq[i][k]=;
}
}
if (g[u][i]<=L && k<K && d[u][k]<d[i][k+]) //如果能够进行加速,并且加速后能更新加速后的状态,则加速,并且保存该状态。
{
d[i][k+]=d[u][k];
if (!inq[i][k+])
{
inq[i][k+]=;
q[rear]=i;
st[rear]=k+;
rear++;
if (rear>maxn)
rear=;
}
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{ scanf("%d%d%d%d%d",&A,&B,&M,&L,&K);
init();
for (int i=;i<=M;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
g[a][b]=g[b][a]=c;
}
floyd();
solve();
int ans=INF;
for (int i=;i<=K;i++)
if (ans>d[][i])
ans=d[][i];
printf("%d\n",ans);
}
return ;
}

其实整个动规过程就是最短路的松弛过程,尤其是它把每个点的状态都求到了,并且把松弛成功(或者说状态转移成功)的点又存贮进了队列,以它来继续寻求更新其他点,这种思想应该可以再用到以后其他的DP问题中

UVA 10269 Super Mario,最短路+动态规划的更多相关文章

  1. zoj1232Adventure of Super Mario(图上dp)

    题目连接: 啊哈哈.点我点我 思路: 这个题目是一个图上dp问题.先floyd预处理出图上全部点的最短路,可是在floyd的时候,把可以用神器的地方预处理出来,也就是转折点地方不能为城堡..预处理完成 ...

  2. UVA10269 Adventure of Super Mario(Floyd+DP)

    UVA10269 Adventure of Super Mario(Floyd+DP) After rescuing the beautiful princess, Super Mario needs ...

  3. HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  4. Teaching Your Computer To Play Super Mario Bros. – A Fork of the Google DeepMind Atari Machine Learning Project

    Teaching Your Computer To Play Super Mario Bros. – A Fork of the Google DeepMind Atari Machine Learn ...

  5. hdu4177:Super Mario

    主席树+离散化.给一段区间.多次询问[l,r]中有多少个数小于k.啊主席树用指针版写出来优美多了QAQ... #include<cstdio> #include<cstring> ...

  6. 主席树:HDU 4417 Super Mario

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. hdu4417 Super Mario 树阵离线/划分树

    http://acm.hdu.edu.cn/showproblem.php?pid=4417 Super Mario Time Limit: 2000/1000 MS (Java/Others)    ...

  8. Super Mario

    Super Mario Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit ...

  9. UVA - 12298 Super Poker II NTT

    UVA - 12298 Super Poker II NTT 链接 Vjudge 思路 暴力开个桶,然后统计,不过会T,用ntt或者fft,ntt用个大模数就行了,百度搜索"NTT大模数&q ...

随机推荐

  1. 设置gvim的字体大小

    1.临时设置: 进入命令行模式输入: set guifont=Courier\ New:h10 2.永久设置: 打开安装目录找到defaults.vim在最后一行输入: set guifont=Cou ...

  2. SpringBoot#JSR303

    __震惊了!,一遍一遍在业务逻辑中编写的验证条件被抽离了! 是什么: - Java Specification Requests 303 ,用于对javaBean 属性的验证. - 解决了什么问题: ...

  3. php.laravel.log

    看代码,原厂代码写的比较清楚,版本(laravel5.7) 简单使用,方便调试,详细使用需要详细查看文档. 在config/app.php 添加 'log' => env('APP_LOG', ...

  4. 解决dispatch 后在当前页面不能获取最新的this.props中的数据

    因为dispatch为异步方法  .解决这个问题方法很多  出去添加定时器这种不是很优雅的方法  我们可以用 componentWillReceiveProps(nextProps) 这个生命周期  ...

  5. QT事件处理–notify()

    转载至:https://www.deeplearn.me/349.html 一.说明 Qt 处理事件的方式之一:”继承 QApplication 并重新实现 notify()函数”.Qt 调用 QAp ...

  6. 054-for循环

    <?php for($i=1;$i<=5;$i++){ echo "$i<br />"; //循环体 } ?>

  7. SQL 、LINQ日前比较

      using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; ...

  8. C++ 99表

    #include<iostream> using namespace std; class Sumes { public: int sum; int i, j; }; int main() ...

  9. servlet的基本类和接口

    javax.servlet.Servlet接口 javax.servlet.GenericServlet类(协议无关版本) javax.servlet.http.HttpServlet类(HTTP版本 ...

  10. c++程序—if语句实践

    三只小 #include<iostream> using namespace std; #include<string> int main() { //which pig is ...