[解説] Leyniカーレース
問題を考えですか?私はハッシュされて驚きました
この前提図トピック状態
\ [ANS(I、J、
F)\] 、iからjまで表す最大 F車両最短の使用
トランスファーケースは、各車両が独自フロイドを実行し、その後等に、中央を列挙するために移しました。
しかし、あなたは言う\(F \)死ぬ、しかし慎重にほとんど変更を考えるためにこれを行うには最高の気分\(\ n)で車が最後に到達するので、できるようになります\(のF \)がする\(N \)取ります分だけで罰金。
分析の複雑さのこの方法は便利ですが、より多くの典型的な例は、そのような質問の範囲があり、間隔の長さがされて(100 \)を\、かどうかを確認する(1E5の\を)\、しかし、あなただけ尋ねるたびに\(O(N ^ 2) \) 暴力、どのようにこのサブタスクについて?ああのダイレクトメモリ!上の合計\(100 \回90 \)異なる間隔ああ
だから我々は、取得する((N ^ 5)O \を \) 実際、私はあまりにも考えていたが、データの複数のセット、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\n",ans[t1][t2][t3]);
}
コード\は(G []は\)である構造Iによって定義される\(Eは[MAXN] [MAXN] \)、\ (G [T] .genは()\)再びフロイド実行されます
我々は最低限の要件があるため、我々は見て、それを最適化を検討カオス転送、決定されたため、実際には、第三のパラメータMin関数に手足を動かし考慮\(F \) 、我々は最小見つける\を(G [T 0] [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("\n"))
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\n",ans[t1][t2][t3]);
}
}
return 0;
}