都市环游
来源:互联网 发布:淘宝访客数是什么意思 编辑:程序博客网 时间:2024/06/09 19:41
都市环游
题目描述
因为SJY干的奇怪事情过多,SJY收到了休假的通知,于是他准备在都市间来回旅游。SJY有一辆车子,一开始行驶性能为0,每过1时间行驶性能就会提升1点。每个城市的道路都有性能要求。SJY一共有t时间休息,一开始他位于1号城市(保证1号城市道路要求为0),他希望在n号城市结束旅程。每次穿过一条城市间的路会花费1时间,当然他也可以停留在一个城市不动而花费1时间。当且仅当车子的行驶性能大于等于一个城市,我们才能到达那里。SJY希望知道,旅游的方案模10086后的答案。(只要在某一时刻通过的道路存在一条不相同,就算不同的方案)
输入
第一行三个数n,m,t,表示有n个城市m条道路t时间。第二行n个数,hi表示第i个城市的道路性能要求。
第三到m+2行,每行两个数u,v,表示城市u与城市v之间有一条单向道路连接(可能有重边)。
输出
包括一个数字,表示旅游的方案模10086。
样例输入
5 17 7
0 2 4 5 3
1 2
2 1
1 3
3 1
1 4
4 1
4 5
5 4
5 3
4 1
2 1
5 3
2 1
2 1
1 2
2 1
1 3
样例输出
245
提示
【数据规模和约定】
对于20%的数据,n<=10,t<=80;对于50%的数据,n<=30,t<=80;对于100%的数据,n<=70,m<=1000,t<=100000000,hi<=70。
solution:
算法1:DP。
f[i][j]表示第j时间到第i个城市的方案数,
f[1][0]=1; for(int j=1;j<=t;j++) for(int i=1;i<=n;i++){ f[i][j]=f[i][j-1]; if(j>=a[i]) for(int e=head[i];e;e=Next[e]) f[i][j]=(f[i][j]+f[vet[e]][j-1])%10086; } printf("%d\n",f[n][t]);
但是……t太大了,这样子只有50分。
时间复杂度O(nt)
算法2:
矩阵乘法
有这样一个结论:要求路径方案数就是把多个邻接矩阵相乘。
把在原地不动看作是自环。
然后,观察到h[i]的值很小,就将前面有性能约束的时间里一个一个做矩阵乘法。后面性能已经足够好,想跑什么城市都可以,就不用关心能不能去那个城市,只关心要用多少时间。这个时间非常的大,一个一个的做乘法肯定是要TLE的,由于每次乘的都一样,用快速幂优化一下就可以了。
要注意这几个细节:在处理前面一部分的邻接矩阵时,要小心性能约束。对于边e(u,v),当时的性能a,当且仅当a>h[u]&&a>=h[v]时这条边可以取用,否则为0。因为这条边可取须有上一时刻可以到达u&&这一时刻可以到达v。我不小心把两个都写成了>=于是就完美的WA了。
这份代码是分类的,防止打错了全炸……将就一下
#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstdlib>#include<cstring>using namespace std;typedef long long ll;ll read(){ ll ans=0; char ch=getchar(),last=' '; while(ch>'9'||ch<'0'){ last=ch; ch=getchar(); } while(ch<='9'&&ch>='0'){ ans=ans*10+ch-'0'; ch=getchar(); } if(last=='-') ans=-ans; return ans;}int mt,nt,tt,n,m,t,a[80],f[80][10000],vet[10000],Next[10000],head[10000],en,ans,ft[75][75],f0[75][75],f2[75][75],fn[75][75];//a就是题目中的hint main(){ n=read(); m=read(); t=read(); for(int i=1;i<=n;i++){ a[i]=read(); mt=max(mt,a[i]); f0[i][i]=1; } for(int i=1;i<=m;i++){ int x,y; x=read(); y=read(); f0[x][y]++; en++; vet[en]=x; Next[en]=head[y]; head[y]=en; } if(t>=10000){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f2[i][j]=f0[i][j]; for(int ntt=1;ntt<=mt;ntt++){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) fn[i][j]=(ntt>a[i]&&ntt>=a[j] ? f0[i][j] : 0); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ ft[i][j]=0; for(int k=1;k<=n;k++) ft[i][j]=(ft[i][j]+f2[i][k]*fn[k][j])%10086; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f2[i][j]=ft[i][j]; } tt=t-mt; nt=1; while(tt){ if(tt&nt){ tt-=nt; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ ft[i][j]=0; for(int k=1;k<=n;k++) ft[i][j]=(ft[i][j]+f2[i][k]*f0[k][j])%10086; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f2[i][j]=ft[i][j]; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ ft[i][j]=0; for(int k=1;k<=n;k++) ft[i][j]=(ft[i][j]+f0[i][k]*f0[k][j])%10086; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f0[i][j]=ft[i][j]; nt<<=1; } printf("%d\n",f2[1][n]); return 0; } f[1][0]=1; for(int j=1;j<=t;j++) for(int i=1;i<=n;i++){ f[i][j]=f[i][j-1]; if(j>=a[i]) for(int e=head[i];e;e=Next[e]) f[i][j]=(f[i][j]+f[vet[e]][j-1])%10086; } printf("%d\n",f[n][t]); return 0;}
- 都市环游
- 都市环游
- 都市环游
- 都市环游
- 环游世界
- 迷茫都市
- 都市流浪者
- 都市精英
- 佛教都市
- 第九都市
- ---45块环游世界---
- 编码巧解称环游戏
- 免费环游世界
- 编码巧解称环游戏
- 飞屋环游记
- 飞屋环游记
- 暖暖环游世界
- 环游四边形 高精度
- 【网络】select服务器
- 第18章 使用WebSocket和 STOMP实现消息功能
- 【解题报告】舞会
- MySQL主键,外键,索引,唯一索引
- NP完全问题——证明EXACT 4SAT是NP完全问题
- 都市环游
- 总结
- Java中的字符串池
- 《android 日期工具类》
- 剑指offer:(35)时间效率和空间效率的平衡 :第一个只出现一次的字符
- 将虚拟按钮映射到屏幕上
- 无限极分类
- ORACLE:prompt、set feedback、set define
- JS生成二维码(兼容各种浏览器及中文)