zoukankan      html  css  js  c++  java
  • 【题解】Leyni的汽车比赛

    【题解】Leyni的汽车比赛

    HRBUST - 1404

    思维题?居然被我凑出来了

    这种图论题先设这样一个状态

    [ans(i,j,f) ]

    表示从i到j,最多使用f个交通工具的最短路

    转移的话,每辆车先自己跑一个Floyd,然后进去就好了,转移枚举中间点。

    但是你说(f)很大,感觉这样做不行了,但是仔细思考一下,最多换(n)辆车就会到达终点,所以让(f)(n)取min就好了。

    这种分析复杂度的方法很好用,还有一个更典型的例子是,一个区间询问题,区间长度是(100),询问是(1e5)的,但是你每次询问只会(O(n^2))的暴力,怎么过这个subtask? 直接记忆化啊!总共就(100 imes 90)个不同的区间啊

    于是我们获得了一个(O(n^5))的做法,我以为可以过,但是有多组数据,交一发T了

    for(register int t=1;t<=m;++t)
         g[t].read(),g[t].gen();
    for(register int t0=1;t0<=m;++t0)
         for(register int f=1;f<=n+2;++f)
              for(register int k=1;k<=n;++k)
                   for(register int t=1;t<=n;++t)
                        for(register int i=1;i<=n;++i)
                             ans[t][i][f]=Min(ans[t][i][f],ans[t][i][f-1],ans[t][k][f-1]+g[t0][k][i],ans[t][k][f-1]+ans[k][i][1]);
    for(register int t=1;t<=r;++t){
         register int t1=qr(),t2=qr(),t3=min(qr()+1,n+1);
         printf("%d
    ",ans[t1][t2][t3]);
    }
    

    代码中(g[]) 是我定义的结构体,里面是一个(e[maxn][maxn])(g[t].gen())是跑一遍floyd

    考虑优化一下,由于我们是要求最小,我们看一下混乱不堪的转移,考虑在Min函数的第三个参数动动手脚,实际上,对于一个确定(f),我们求一个最小的(g[t0][k][i])就好了,我们随便找个东西存一下就完事了。

    实际上我这份转移靠感觉的代码做了这件事情,就是(ans[t][k][f-1]+ans[k][i][1]),这里(ans[k][i][1])实际上就记录了最小的(g[t0][k][i])。所以我们少枚举一个(t0),复杂度变为(O(n^4))

    本来这种思维题我是做不出来的,但d 是为啥我又写出来了?因为我发现可以通过观察代码的行为来优化算法。。。我用这种技巧已经帮助我在模拟赛里多拿了好几百分了23333333

    没有退役全靠它

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;  typedef long long ll;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57)f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    
    const int maxn=51;
    const int inf=0x3f3f3f3f;
    int ans[maxn][maxn][53];
    int n,m,r;
    struct Graph{
          int e[maxn][maxn];
          inline void read(){
    	    for(register int t=1;t<=n;++t)
    		  for(register int i=1;i<=n;++i)
    			e[t][i]=qr();
          }
          inline int* operator [](register int x){return e[x];}
          inline void gen(){
    	    for(register int k=1;k<=n;++k)
    		  for(register int t=1;t<=n;++t)
    			for(register int i=1;i<=n;++i)
    			      e[t][i]=min(e[t][i],e[t][k]+e[k][i]);
          }
          inline void print(){
    	    for(register int t=1;t<=n;++t,printf("
    "))
    		  for(register int i=1;i<=n;++i)
    			printf("%d ",e[t][i]);
          }
    }g[maxn];
    
    inline int Min(const int&a,const int&b){if(a<b) return a;   return b;}
    inline int Min(const int&a,const int&b,const int&c){return Min(a,min(b,c));}
    inline int Min(const int&a,const int&b,const int&c,const int&d){return Min(a,Min(b,c,d));}
    
    int main(){
          while(scanf("%d %d %d",&n,&m,&r)!=EOF){
    	    for(register int t=0;t<=n;++t)
    		  for(register int i=0;i<=n;++i)
    			for(register int k=0;k<=n+2;++k)
    			      ans[t][i][k]=inf;
    	    for(register int t=1;t<=n;++t) ans[t][t][0]=0;
    	    for(register int t=1;t<=m;++t){
    		  g[t].read(),g[t].gen();
    		  for(register int i=1;i<=n;++i)
    			for(register int k=1;k<=n;++k)
    			      ans[i][k][1]=min(ans[i][k][1],g[t][i][k]);
    	    }
    	    for(register int f=1;f<=n+2;++f)
    		  for(register int k=1;k<=n;++k)
    			for(register int t=1;t<=n;++t)
    			      for(register int i=1;i<=n;++i)
    				    ans[t][i][f]=Min(ans[t][i][f],ans[t][i][f-1],ans[t][k][f-1]+ans[k][i][1]);
    	    for(register int t=1;t<=r;++t){
    		  register int t1=qr(),t2=qr(),t3=min(qr()+1,n+1);
    		  printf("%d
    ",ans[t1][t2][t3]);
    	    }
          }
          return 0;
    }
    
    
    
  • 相关阅读:
    MapReduce-shuffle过程详解
    YARN中的失败分析
    HBase协处理器的使用(添加Solr二级索引)
    Flume具体应用(多案例)
    Flume架构及运行机制
    python Cmd实例之网络爬虫应用
    mongodb3 权限认证问题总结
    webpack配置
    apt软件包管理
    python笔记之编程风格大比拼
  • 原文地址:https://www.cnblogs.com/winlere/p/11409244.html
Copyright © 2011-2022 走看看