都市环游

题目描述
因为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。

对于50%的数据,很容易想到dp转移方程,记dp[i,j]表示i时刻到j点的方案总数,dp[i,j]=dp[i-1,k]*a[k,j]; a[k,j]为k到j的路经数。

对于100%的数据,我们发现hi<=70,也就是说70s以后我们就可以随便走了,于是我们想到了矩阵乘法,70s以后直接用矩阵算,70s之前用dp算。

type al=array[0..80,0..80] of longint;
var
n,m,t,i,x,y,j,k:longint;
a,dp,f,ans:al;
h:array[0..1000] of longint;
function chen(x,y:al):al;
var
i,j,k:longint;
begin
  for i:=1 to n do
    for j:=1 to n do
    begin
      chen[i,j]:=0;
      for k:=1 to n do
        chen[i,j]:=(chen[i,j]+x[i,k]*y[k,j]) mod 10086;
    end;
end;

function gpow(k:longint):al;
var
t:al;
begin
  if k=1 then exit(a);
  t:=gpow(k div 2);
  t:=chen(t,t);
  if k mod 2=1 then t:=chen(t,a);
  exit(t);
end;

begin
  readln(n,m,t);
  for i:=1 to n do
    read(h[i]);
  readln;
  for i:=1 to m do
  begin
    readln(x,y);
    a[x,y]:=a[x,y]+1;
  end;
  for i:=1 to n do
    a[i,i]:=a[i,i]+1;
  dp[0,1]:=1;
  for i:=1 to 70 do
    for j:=1 to n do
      for k:=1 to n do
       if (i>=h[k])and(a[j,k]>0) then dp[i,k]:=(dp[i,k]+dp[i-1,j]*a[j,k]) mod 10086;
  if t<=70 then write(dp[t,n])
  else
  begin
    ans:=gpow(t-70);
    for i:=1 to n do
      for k:=1 to n do
        dp[71,k]:=(dp[71,k]+dp[70,i]*ans[i,k]) mod 10086;
    write(dp[71,n]);
  end;
end.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值