题目描述:

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

策策每天都会去逛公园,他总是从1号点进去,从N号点出来。

策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果1号点 到N号点的最短路长为d,那么策策只会喜欢长度不超过d + K的路线。

策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?

为避免输出过大,答案对P取模。

如果有无穷多条合法的路线,请输出-1。

题解:

话说去年提高组的难度真心大.......

我们一层一层考虑这道题:

1.首先,我们发现 $k<=50$,这个规模是非常小的。

2.由发现一,我们不难列出 dp 状态:$dp[i][j]$ 代表第 $i$ 号点到终点的距离比最短路大 $j$ 的方案数。

对于2的实现,我们考虑将每条边反着连

从N 点开始跑一遍到 1 号点的最短路,求出每个点到 N 号点的最短路。

我们这么做的原因是由于正着做可能会碰到不合法的状态,而逆推则不会碰到非法状态。

因为显然,1 号点的最短路径一定是全局的最短路径,于是可以由 1 号点转移的状态就全部是合法的,依此类推。

考虑正着进行记忆化搜索,从一个点转移到另一个点时,所需要走的最短路径为 $d[v]+w$。

而原本的最短路径为 $d[u]$,那么这就比 $d[u]$ 多了 $d[v]+w-d[u]$ 的路程。

假设当前的偏移量(即比最短路多出的量)为 $k$。

那么转移到 $v$ 点之后的偏移量就会变成 $k-(d[v]+w-d[u])$

我们这么进行记忆化搜索即可。

不过我们还要判一下 0 环。 开一个 $vis[i][k]$ 数组即可。

发现该状态再一次被访问且 $vis[i][k]=true$ 就说明出现 0 环,直接输出 -1.

Code:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
using namespace std;
const int maxn=400000+4;
int d[maxn],s, n ,m, mod,tot;
struct SPFA{int head[maxn],to[maxn],nex[maxn],val[maxn],cnt;void addedge(int u,int v,int c){nex[++cnt]=head[u],head[u]=cnt,to[cnt]=v,val[cnt]=c;}queue<int>Q;bool inq[maxn];void init(){memset(head,0,sizeof(head)), memset(to,0,sizeof(to)), memset(nex,0,sizeof(nex)), memset(val,0,sizeof(val));cnt=0;}void spfa(){memset(d,0x3f,sizeof(d));memset(inq,false,sizeof(inq));d[s]=0,inq[s]=true; Q.push(s);while(!Q.empty()){int u=Q.front();Q.pop(); inq[u]=false;for(int v=head[u];v;v=nex[v]){if(d[u]+val[v]<d[to[v]]){d[to[v]]=d[u]+val[v];if(!inq[to[v]]){ Q.push(to[v]); inq[to[v]]=true; }}}}}
}T;
int head[maxn], to[maxn], nex[maxn], val[maxn], cnt;
void addedge(int u,int v,int c){nex[++cnt]=head[u], head[u]=cnt, to[cnt]=v, val[cnt]=c;
}
int dp[100007][60];
bool vis[100007][60];
int dfs(int u,int k){if(vis[u][k]) return -1;if(dp[u][k]!=-1) return dp[u][k];vis[u][k]=1;int sum=0;for(int v=head[u];v;v=nex[v]){int tmp=k-(d[to[v]]+val[v]-d[u]);if(tmp<0||tmp>tot) continue;int delta=dfs(to[v], tmp);if(delta==-1) return -1;sum=(sum+delta)%mod;     }if(k==0&&u==n) sum+=1;vis[u][k]=0;dp[u][k]=sum;return sum;
}
int work(){memset(dp,-1,sizeof(dp)); memset(head,0,sizeof(head));memset(to,0,sizeof(to));memset(val,0,sizeof(val));cnt=0;T.init();scanf("%d%d%d%d",&n,&m,&tot,&mod); for(int i=1;i<=m;++i){int a,b,c;scanf("%d%d%d",&a,&b,&c);T.addedge(b,a,c);                         // 返向addedge(a,b,c);                           // 正向}s=n;T.spfa();int ans=0;for(int i=0;i<=tot;++i){memset(vis,0,sizeof(vis));int aa=dfs(1,i);if(aa==-1) return -1;ans=(ans+aa)%mod;}return ans;
}
int main(){     int T;     scanf("%d",&T);     while(T--) printf("%d\n",work());      return 0;
}

  

NOIP 2017 逛公园 记忆化搜索 最短路 好题相关推荐

  1. 洛谷3953 (NOIp2017) 逛公园——记忆化搜索+用栈判0环

    题目:https://www.luogu.org/problemnew/show/P3953 因为K只有50,所以想到用dp[ cr ][ j ]表示在点cr.比最短路多走了 j 的方案数.(看了TJ ...

  2. NOIP 2017 逛公园

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

  3. 2017广东工业大学程序设计竞赛决赛 题解源码(A,数学解方程,B,贪心博弈,C,递归,D,水,E,贪心,面试题,F,贪心,枚举,LCA,G,dp,记忆化搜索,H,思维题)...

    心得: 这比赛真的是不要不要的,pending了一下午,也不知道对错,直接做过去就是了,也没有管太多! Problem A: 两只老虎 Description 来,我们先来放松下,听听儿歌,一起&qu ...

  4. 【BZOJ1048】分割矩阵(记忆化搜索,动态规划)

    [BZOJ1048]分割矩阵(记忆化搜索,动态规划) 题面 BZOJ 洛谷 题解 一个很简单的\(dp\),写成记忆化搜索的形式的挺不错的. #include<iostream> #inc ...

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

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

  6. LOJ #2316「NOIP2017」逛公园【最短路】【记忆化搜索】

    dis[i]dis[i]dis[i]表示111号点到iii号点的最短距离,用spfaspfaspfa跑一遍即可. 考虑如何设定状态. 注意到题意要的是小于等于dis[n]+Kdis[n]+Kdis[n ...

  7. NOIP2017 逛公园(最短路+记忆化搜索)

    Description Input Output Example 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 ...

  8. 终于结束的起点(滚动数组,记忆化搜索)

    任意门 终于结束的起点 题目背景 终于结束的起点 终于写下句点 终于我们告别 终于我们又回到原点 -- 一个个 OIer 的竞赛生涯总是从一场 NOIp 开始,大多也在一场 NOIp 中结束,好似一次 ...

  9. 【codevs 1090】加分二叉树(记忆化搜索)

    1090 加分二叉树2003年NOIP全国联赛提高组  时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description   设一个n个节点的二 ...

最新文章

  1. C++ map的使用
  2. Android OpenGL ES 入门系列(一) --- 了解OpenGL ES的前世今生
  3. python代码编辑器-世界上最好的Python编辑器是什么?
  4. python3各个版本是通用的吗-python3各版本
  5. 10张劲爆眼球的科学动图
  6. P1032-字串变换【bfs】
  7. 102_Power Pivot DAX 排名后加上总排名数
  8. 95-38-050-Buffer-UnpooledHeapByteBuf
  9. 中国水稻种子行业市场供需与战略研究报告
  10. zabbix自定义监控Key值
  11. [转载] Java基础之构造方法(函数)何时被调用
  12. Git教程、python教程、ubuntu教程 收藏
  13. 安装mp4,mp3等媒体解码器
  14. 郝斌C语言 printf与scanf的用法
  15. 犬类水疗跑步机的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  16. Python入门(四):Python变量
  17. 乐天店铺网页制作、装修简要教程
  18. linux execl()函数
  19. 有哪些适合新手的练手Java项目?
  20. 【Python】照片扩展信息提取

热门文章

  1. 2005年的网易邮箱长什么样的?
  2. bash shell:获取当前脚本的绝对路径(pwd/readlink)
  3. 字符串常量池,看这篇就够了(一)
  4. 程序媛是怎样找老公的(2018版)
  5. EAUML日拱一卒-微信小程序实战:位置闹铃 (17)-保存和取出设定信息
  6. 教你们1秒钟复制百度文库中所有内容
  7. 2022帆软杯全国高校数据分析与应用联赛来啦!
  8. Ten tools for sharepoint development
  9. 小觅摄像头Opencv处理
  10. Win11的两个实用技巧系列之dns异常和打印机重命名