逛公园 [NOIP2017 D1T3] [记忆化搜索]
Description
策策同学特别喜欢逛公园。公园可以看成一张N个点M条边构成的有向图,且没有自环和重边。其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值,代表策策经过这条边所要花的时间。
策策每天都会去逛公园,他总是从1号点进去,从N号点出来。
策策喜欢新鲜的事物,他不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,他不希望每天在逛公园这件事上花费太多的时间。如果1号点到N号点的最短路长为d,那么策策只会喜欢长度不超过d+K的路线。
策策同学想知道总共有多少条满足条件的路线,你能帮帮他吗? 为避免输出过大,答案对P取模。 如果有无穷多条合法的路线,请输出−1。
Input
第一行包含一个整数 T, 代表数据组数。 接下来T组数据,对于每组数据:
第一行包含四个整数 N,M,K,P,每两个整数之间用一个空格隔开。
接下来M行,每行三个整数ai,bi,ci,代表编号为ai、bi的点之间有一条权值为ci的有向边,每两个整数之间用一个空格隔开。
Output
包含T行,每行一个整数代表答案。
Sample Input
2
5 7 2 10
1 2 1
2 4 0
4 5 2
2 3 2
3 4 1
3 5 2
1 5 3
2 2 0 10
1 2 0
2 1 0
Sample Output
3
-1
说明
【样例解释1】
对于第一组数据,最短路为 3 。 1 – 5, 1 – 2 – 4 – 5, 1 – 2 – 3 – 5 为 3条合法路径。
【测试数据与约定】
对于不同的测试点,我们约定各种参数的规模不会超过如下
| 测试点编号 | TT | NN | MM | KK | 是否有0边 |
|---|---|---|---|---|---|
| 1 | 5 | 5 | 10 | 0 | 否 |
| 2 | 5 | 1000 | 2000 | 0 | 否 |
| 3 | 5 | 1000 | 2000 | 50 | 否 |
| 4 | 5 | 1000 | 2000 | 50 | 否 |
| 5 | 5 | 1000 | 2000 | 50 | 否 |
| 6 | 5 | 1000 | 2000 | 50 | 是 |
| 7 | 5 | 100000 | 200000 | 0 | 否 |
| 8 | 3 | 100000 | 200000 | 50 | 否 |
| 9 | 3 | 100000 | 200000 | 50 | 是 |
| 10 | 3 | 100000 | 200000 | 50 | 是 |
数据保证:至少存在一条合法的路线。
分析
我真的是太弱了,考场上写了一个A星,结果过的全是K=0的,然后就只有30分了(t1t2已让我心态爆炸)
我们看数据,K≤50,我们可以比较容易地想到dp,如何设状态?
我们记dis[u]为u点到n的最短路,我们走完一条方案希望整个距离不超过dis[1]+K
那我们就记录下到每个点的剩余额度rem,我们希望剩余额度尽可能大,就有更多精力走更多的路
对于一条边edge(u,v,val)
如果不走这条边,从u出发的最小代价为dis[u](记录最小代价就是为了剩余额度尽可能大,到下个路口有更多的选择)
如果我们走了这条边,从u出发的最小代价为val+dis[v]
那么剩余额度就是rem-(dis[v]+val-dis[u]),如果(dis[v]+val-dis[u])>rem 此方案无效
那么我们看出来方案数和当前所在的点u和剩余额度rem有关,那么我们记录方案数为dp[u][rem],根据上面分析可以知道dp[u][rem]+=dp[v][rem-(dis[v]+val-dis[u])],记忆化搜索即可。
到了终点不论剩余额度是多少,一开始给了k的额度,只要最后的额度≥0即可。
如何对付0边?记录下状态vis[u][rem]即可,如果再次访问就返回-1
代码
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define RG register int
#define rep(i,a,b) for(RG i=a;i<=b;++i)
#define per(i,a,b) for(RG i=a;i>=b;--i)
#define ll long long
#define inf (1<<29)
#define maxn 100005
#define maxm 200005
#define add(x,y,z) e[++cnt]=(E){y,head[x],z},head[x]=cnt
using namespace std;
int T,n,m,K,p,cnt,ans,flg;
int head[maxn],vis[maxn][],dp[maxn][],dis[maxn];
struct E{
int v,next,val;
}e[maxm];
inline int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} void init()
{
memset(head,,sizeof(head));
memset(dis,,sizeof(dis));
memset(vis,,sizeof(vis));
memset(dp,,sizeof(dp));
cnt=ans=flg=;
} inline int mod(int a){return a>=p?a-p:a;} namespace PRE{
int head[maxn],vis[maxn],cnt; struct E{
int v,next,val;
}e[maxm]; void ad(int x,int y,int z) {e[++cnt]=(E){y,head[x],z},head[x]=cnt;} void init(){memset(head,,sizeof(head));cnt=;} void spfa()
{
queue<int> que;que.push(n),dis[n]=;
RG u,v;
while(!que.empty())
{
u=que.front(),que.pop();
for(RG i=head[u];i;i=e[i].next)
{
v=e[i].v;
if(dis[v]>dis[u]+e[i].val)
{
dis[v]=dis[u]+e[i].val;
if(!vis[v]) vis[v]=,que.push(v);
}
}
vis[u]=;
}
} } int dfs(int u,int rem)
{
if(dp[u][rem]) return dp[u][rem];
if(vis[u][rem]) return dp[u][rem]=-;
vis[u][rem]=-;
int res,v,ret;
if(u==n) dp[u][rem]=;
for(int i=head[u];i;i=e[i].next)
{
v=e[i].v;
res=dis[v]+e[i].val-dis[u];
if(res>rem) continue;
if((ret=dfs(v,rem-res))==-) return dp[u][rem]=-;
dp[u][rem]=mod(ret+dp[u][rem]);
}
vis[u][rem]=;
return dp[u][rem];
} int main()
{
freopen("data7.in","r",stdin);
T=read();
while(T--)
{
init();PRE::init();
n=read(),m=read(),K=read(),p=read();
for(RG i=,u,v,val;i<=m;i++) u=read(),v=read(),val=read(),add(u,v,val),PRE::ad(v,u,val);
PRE::spfa();
memset(vis,,sizeof(dp));
ans=dfs(,K);printf("%d\n",ans);
}
return ;
}
逛公园 [NOIP2017 D1T3] [记忆化搜索]的更多相关文章
- luogu3953 [NOIp2017]逛公园 (tarjan+dijkstra+记忆化搜索)
先跑一边dijkstra算出从1到i的最短距离dis[i] 然后建反向边 从n开始记忆化搜索,(p,k)表示1到p的距离=dis[p]+k的方案数 答案就是$\sum\limits_{i=0}^{k} ...
- Luogu P3953 逛公园(最短路+记忆化搜索)
P3953 逛公园 题面 题目描述 策策同学特别喜欢逛公园.公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边.其中 \(1\) 号点是公园的入口,\(N\) 号点是公 ...
- 洛谷 P3953 逛公园【spfa+记忆化dfs+bfs】
spfa预处理出最短路数组dis,然后反向建边bfs出ok[u]表示u能到n点 然后发现有0环的话时候有inf解的,先dfs找0环判断即可 然后dfs,设状态f[u][v]为到u点,还可以跑最短路+v ...
- 【NOIP2017】逛公园 拆点最短路+拓扑(记忆化搜索
题目描述 策策同学特别喜欢逛公园.公园可以看成一张N个点M条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. 策 ...
- Luogu 3953[NOIP2017] 逛公园 堆优化dijkstra + 记忆化搜索
题解 首先肯定是要求出单源最短路的,我用了堆优化dijikstra ,复杂度 mlogm,值得拥有!(只不过我在定义优先队列时把greater 打成了 less调了好久 然后我们就求出了$i$到源点的 ...
- [NOIP2017] 逛公园 (最短路,动态规划&记忆化搜索)
题目链接 Solution 我只会60分暴力... 正解是 DP. 状态定义: \(f[i][j]\) 代表 \(1\) 到 \(i\) 比最短路长 \(j\) 的方案数. 那么很显然最后答案也就是 ...
- 洛谷3953 (NOIp2017) 逛公园——记忆化搜索+用栈判0环
题目:https://www.luogu.org/problemnew/show/P3953 因为K只有50,所以想到用dp[ cr ][ j ]表示在点cr.比最短路多走了 j 的方案数.(看了TJ ...
- 【洛谷】3953:逛公园【反向最短路】【记忆化搜索(DP)统计方案】
P3953 逛公园 题目描述 策策同学特别喜欢逛公园.公园可以看成一张N个点M条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条 ...
- NOIP 2017 逛公园 记忆化搜索 最短路 好题
题目描述: 策策同学特别喜欢逛公园.公园可以看成一张N个点MM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. ...
随机推荐
- 2018-2019-2 网络对抗技术 20165337 Exp3 免杀原理与实践
基础问题回答 (1)杀软是如何检测出恶意代码的? 基于特征码的检测:特征码就是一段数据.如果一个可执行文件(或其他运行的库.脚本等)包含特定的数据则被认为是恶意代码.AV软件厂商要做的就是尽量搜集最全 ...
- [系统集成] 基于 elasticsearch 的企业监控方案
注: 2017年10月16日: 使用中发现 es 查询时序数据的性能较差,且 watch 脚本的编写比较麻烦,因此已将监控系统切换到了 influxdb+grafana平台.新监控系统各方面情况比较满 ...
- HDU - 1035
wa了一遍,炸了两遍 (1)迷宫题中的模拟题.只需要简单代码就可以ac.如果程序有问题,最后就会卡死,出现runtime error. (2)边界问题一定要小心,数组是从0开始的,就要考虑r--会不会 ...
- SHOT
- 3D Slicer中文教程(八)—导出STL文件
一.STL文件简介 STL(立体平版印刷术的缩写)是由3D Systems创建的立体平版印刷CAD软件原生的文件格式STL有“标准三角语言”和“标准镶嵌语言”等几个事后回溯.这种文件格式是由许多其他软 ...
- 基于python的WGS84转百度坐标
from urllib.request import urlopen, quote import json def wgs84tobaidu(x,y): data=str(x)+','+str(y); ...
- JSX的替代方案(译文)
原文链接:https://blog.bloomca.me/2019/02/23/alternatives-to-jsx.html JSX作为一种流行的模板语言,在各种框架都得到了广泛的应用.但是,如果 ...
- django orm 及常用参数
一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...
- SQL语句完整的执行顺序(01)
一.sql语句的执行步骤: 1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义. 2) 语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限. 3)视图转换,将涉 ...
- Linux基础-命令(续)
touch 命令: 如果文件不存在,创建文件, 如果文件存在,则修改文件最后修改时间. mkdir 命令: -p 递归创建目录,如,mkdir -p a/b/c/d Linux 中同一目录 ...