• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Retarded_ZY
博客园    首页    新随笔    联系   管理    订阅  订阅

都市环游

都市环游

题目描述

因为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了。
这份代码是分类的,防止打错了全炸……将就一下

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstdlib>
  6 #include<cstring>
  7 using namespace std;
  8 typedef long long ll;
  9 ll read(){
 10     ll ans=0;
 11     char ch=getchar(),last=' ';
 12     while(ch>'9'||ch<'0'){
 13         last=ch;
 14         ch=getchar();
 15     }
 16     while(ch<='9'&&ch>='0'){
 17         ans=ans*10+ch-'0';
 18         ch=getchar();
 19     }
 20     if(last=='-')
 21         ans=-ans;
 22     return ans;
 23 }
 24 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就是题目中的h
 25 int main(){
 26     n=read();
 27     m=read();
 28     t=read();
 29     for(int i=1;i<=n;i++){
 30         a[i]=read();
 31         mt=max(mt,a[i]);
 32         f0[i][i]=1;
 33     }
 34     for(int i=1;i<=m;i++){
 35         int x,y;
 36         x=read();
 37         y=read();
 38         f0[x][y]++;
 39         en++;
 40         vet[en]=x;
 41         Next[en]=head[y];
 42         head[y]=en;
 43     }
 44     if(t>=10000){
 45         for(int i=1;i<=n;i++)
 46             for(int j=1;j<=n;j++)
 47                 f2[i][j]=f0[i][j];
 48         for(int ntt=1;ntt<=mt;ntt++){
 49             for(int i=1;i<=n;i++)
 50                 for(int j=1;j<=n;j++)
 51                     fn[i][j]=(ntt>a[i]&&ntt>=a[j] ? f0[i][j] : 0);
 52             for(int i=1;i<=n;i++)
 53                 for(int j=1;j<=n;j++){
 54                     ft[i][j]=0;
 55                     for(int k=1;k<=n;k++)
 56                         ft[i][j]=(ft[i][j]+f2[i][k]*fn[k][j])%10086;
 57                 }
 58             for(int i=1;i<=n;i++)
 59                 for(int j=1;j<=n;j++)
 60                     f2[i][j]=ft[i][j];
 61         }
 62         tt=t-mt;
 63         nt=1;
 64         while(tt){
 65             if(tt&nt){
 66                 tt-=nt;
 67                 for(int i=1;i<=n;i++)
 68                     for(int j=1;j<=n;j++){
 69                         ft[i][j]=0;
 70                         for(int k=1;k<=n;k++)
 71                             ft[i][j]=(ft[i][j]+f2[i][k]*f0[k][j])%10086;
 72                     }
 73                 for(int i=1;i<=n;i++)
 74                     for(int j=1;j<=n;j++)
 75                         f2[i][j]=ft[i][j];
 76             }
 77             for(int i=1;i<=n;i++)
 78                 for(int j=1;j<=n;j++){
 79                     ft[i][j]=0;
 80                     for(int k=1;k<=n;k++)
 81                         ft[i][j]=(ft[i][j]+f0[i][k]*f0[k][j])%10086;
 82                 }
 83             for(int i=1;i<=n;i++)
 84                 for(int j=1;j<=n;j++)
 85                     f0[i][j]=ft[i][j];
 86             nt<<=1;
 87         }
 88         printf("%d\n",f2[1][n]);
 89         return 0;
 90     }
 91     f[1][0]=1;
 92     for(int j=1;j<=t;j++)
 93         for(int i=1;i<=n;i++){
 94             f[i][j]=f[i][j-1];
 95             if(j>=a[i])
 96                 for(int e=head[i];e;e=Next[e])
 97                     f[i][j]=(f[i][j]+f[vet[e]][j-1])%10086;
 98         }
 99     printf("%d\n",f[n][t]);
100     return 0;
101 }

 

  

posted @ 2017-07-11 16:46  Retarded_ZY  阅读(308)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3