题目链接


Solution

我只会60分暴力...

正解是 DP.

状态定义:

\(f[i][j]\) 代表 \(1\) 到 \(i\) 比最短路长 \(j\) 的方案数.

那么很显然最后答案也就是 \(\sum^{i=0}_{k}f[n][i]\).

转移方程:

对于任一状态 \(f[i][j]\) 我们对可以到达它的点 \(v\) 进行讨论:

  1. \(v\) 本身为 \(1\) 到 \(i\) 的最短路上的节点,则此时 $$f[i][j]+=f[v][j]$$
  2. 若 \(v\) 并非到其最短路上的点.

    那么此时从 \(v\) 到 \(i\) 相当于多走了\((dis[i]-(dis[v]+w_{v,i}))\)这么长.

    所以此时 $$f[i][j]+=f[v][j-(dis[i]-(dis[v]+w_{v,i}))]$$

然后很明显 \(1\) 也可以表示为 \(2\) 状态.

所以 \(2\) 状态即为总动态转移方程.

\(0\) 环:

由于题目中给出的图并非一张 \(DAG\) ,所以可能存在 \(0\) 环的情况.

如果 \(DP\) 从前往后推,那么可以使用拓扑排序.

记忆化搜索则需要判断一种状态是否在一次搜索时出现多次.

此处给出记忆化搜索的代码.

Code

#include<bits/stdc++.h>
#define in(x) x=read()
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=100008; struct node{int u; ll d;
bool operator <(const node& kkk)const
{return d>kkk.d;}
};
struct sj{int to,next;ll w;}a[maxn*4];
int head[maxn],size,Head[maxn];
ll f[maxn][52],dis[maxn],ans;
int n,m,k,mod,c[maxn][52],ff;
int v[maxn][52],vis[maxn]; int read()
{
char ch=getchar(); int f=1,w=0;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
return f*w;
} void add(int x,int y,int w)
{a[++size].to=y;a[size].next=head[x];head[x]=size;a[size].w=w;}
void Add(int x,int y,int w)
{a[++size].to=y;a[size].next=Head[x];Head[x]=size;a[size].w=w;} void Dijkstra()
{
priority_queue<node>q;
memset(dis,127,sizeof(dis));
q.push((node){1,0});
dis[1]=0;
while(!q.empty())
{
node x=q.top();q.pop();
int u=x.u;
for(int i=head[u];i;i=a[i].next)
{
int tt=a[i].to;
if(dis[tt]>dis[u]+a[i].w)
{
dis[tt]=dis[u]+a[i].w;
q.push((node){tt,dis[tt]});
}
}
}
return;
} ll dfs(int x,int kk)
{
if(v[x][kk])return f[x][kk];
v[x][kk]=1;
c[x][kk]=1;
if(ff==1)return 0;
for(int i=Head[x];i;i=a[i].next)
{
int tt=a[i].to;
int t=dis[x]+kk-a[i].w-dis[tt];
if(t<0)continue;
if(c[tt][t]){ff=1;return 0;}
f[x][kk]+=dfs(tt,t);
f[x][kk]%=mod;
}
c[x][kk]=0;
return f[x][kk];
} int main()
{
int t; in(t);
while(t--)
{
//Init
memset(c,0,sizeof(c));
memset(v,0,sizeof(v));
memset(dis,127,sizeof(dis));
memset(Head,0,sizeof(Head));
memset(head,0,sizeof(head));
memset(a,0,sizeof(a)); size=0;
memset(f,0,sizeof(f)); ff=0; //Input
in(n); in(m); in(k); in(mod);
for(int i=1;i<=m;i++)
{
int x,y,z; in(x),in(y),in(z);
add(x,y,z); Add(y,x,z);
}
Dijkstra(); //dfs + DP
ans=0;
f[1][0]=v[1][0]=1;
for(int i=0;i<=k;i++)
{
dfs(n,i),ans+=f[n][i],ans%=mod;
if(ff==1)break;
}
dfs(n,k+1);
if(ff==1)
{printf("-1\n");continue;} printf("%lld\n",ans);
}
}

[NOIP2017] 逛公园 (最短路,动态规划&记忆化搜索)的更多相关文章

  1. Luogu 3953[NOIP2017] 逛公园 堆优化dijkstra + 记忆化搜索

    题解 首先肯定是要求出单源最短路的,我用了堆优化dijikstra ,复杂度 mlogm,值得拥有!(只不过我在定义优先队列时把greater 打成了 less调了好久 然后我们就求出了$i$到源点的 ...

  2. sicily 1176. Two Ends (Top-down 动态规划+记忆化搜索 v.s. Bottom-up 动态规划)

    Description In the two-player game "Two Ends", an even number of cards is laid out in a ro ...

  3. 【NOIP2017】逛公园 拆点最短路+拓扑(记忆化搜索

    题目描述 策策同学特别喜欢逛公园.公园可以看成一张N个点M条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. 策 ...

  4. Codevs_1017_乘积最大_(划分型动态规划/记忆化搜索)

    描述 http://codevs.cn/problem/1017/ 给出一个n位数,在数字中间添加k个乘号,使得最终的乘积最大. 1017 乘积最大 2000年NOIP全国联赛普及组NOIP全国联赛提 ...

  5. Poj-P1088题解【动态规划/记忆化搜索】

    本文为原创,转载请注明:http://www.cnblogs.com/kylewilson/ 题目出处: http://poj.org/problem?id=1088 题目描述: 区域由一个二维数组给 ...

  6. UVA_437_The_Tower_of_the_Babylon_(DAG上动态规划/记忆化搜索)

    描述 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  7. 滑雪---poj1088(动态规划+记忆化搜索)

    题目链接:http://poj.org/problem?id=1088 有两种方法 一是按数值大小进行排序,然后按从小到大进行dp即可: #include <iostream> #incl ...

  8. [NOIP2017]逛公园 最短路+拓扑排序+dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的有向图,边权为非负整数.求满足路径长度小于等于 $1$ 到 $n$ 最短路 $+k$ 的 $1$ 到 $n$ 的路径条数模 $p$ ,如果有无数条则输出 ...

  9. [NOIP2017]逛公园 最短路图 拓扑序DP

    ---题面--- 题解: 挺好的一道题. 首先我们将所有边反向,跑出n到每个点的最短路,然后f[i][j]表示从i号节点出发,路径长比最短路大j的方案数. 观察到,如果图中出现了0环,那么我们可以通过 ...

随机推荐

  1. [CV笔记]图像特征提取三大法宝:HOG特征,LBP特征,Haar特征

    (一)HOG特征 1.HOG特征: 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子.它通过计算和 ...

  2. groupadd - 建 立 新 群 组

    总览 SYNOPSIS groupadd [-g gid [-o]] [-r] [-f] group 描述 DESCRIPTION groupadd 可 指 定 群 组 名 称 来 建 立 新 的 群 ...

  3. OpenCascade:Topo类型转换

    OpenCascade:Topo类型转换 TopoDS_Edge newEdge; if (oldShape.ShapeType()==TopAbs_EDGE) newEdge=TopoDS::Edg ...

  4. Vmware 安装CentOS7时连不上网问题的解决

    在VmWare 上安装Centos7时,装好vmware后还是连不上网,通过查找资料原来是因为有线网卡没有激活,默认centos和redhat7都是不启用有线网卡的,要么手动开启,要么安装时直接启用! ...

  5. javaweb基础(21)_两种开发模式

    SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一种是JSP+JavaBean模式,一种是Servlet+JSP+JavaBean模式. 一.JSP+JavaBean开发模式 1 ...

  6. Bootstrap历练实例:激活导航状态

    激活导航状态 您可以在激活状态的胶囊式导航和列表导航中放置徽章.通过使用 <span class="badge"> 来激活链接,如下面的实例所示: <!DOCTY ...

  7. Nginx超时配置

    Nginx超时配置 1.client_header_timeout 语法client_header_timeout time 默认值60s 上下文http server 说明 指定等待client发送 ...

  8. 51nod——1548 欧姆诺姆和糖果

    一开始以为是贪心,然后发现没法贪.暴力枚举肯定T,于是用约束关系优化: 假设wr >= wb, 第一种情况:wr >= sqrt (c), 则此时最多吃c / wr个r,且c / wr & ...

  9. 51nod——1391 01串(字符串、前缀和)

    好像这题是4级题下放2级? 预处理:求每个位置 x 左区间 [ 0 , x ] 中 1 比 0 多的数量和右区间 ( x , n - 1 ] 中 0 比 1 多的数量(少就是负的).相当于求两个前缀和 ...

  10. 使用kickstart + pxe 部署无人值守安装

    1.作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装. 常规的安装系统方法: 光盘安装系统:一个服务器DVD内置光驱百 ...