1. 程式人生 > 資訊 >迅雷第三季度營收 6000 萬美元同比增 37.3%,因減少廣告導致此類營收下降 29%

迅雷第三季度營收 6000 萬美元同比增 37.3%,因減少廣告導致此類營收下降 29%

原題連結

分析

通過簡單分析題目,我們知道,我們要計算的就是。

隨著不斷有點被啟用,隨之而來的邊也逐漸可用的情況下,問在某情況下的兩點之間的最小值

本題的重要程度*:提高+/省選-

需要明白Floyd演算法的本質才能很好地寫出這道題

讓我們首先從Floyd演算法談起,這看上去是一個非常簡單的程式碼,實際上它確實也非常簡潔。

for(k=1;k<=n;k++)
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            if(e[i][j]>e[i][k]+e[k][j])
                 e[i][j]=e[i][k]+e[k][j];

演算法本質:動態規劃,就是通過其他的點進行中轉來求的兩點之間的最短路。因為我們知道,兩點之間有多條路,如果換一條路可以縮短距離的話,就更新最短距離。而它最本質的思想,就是用其他的點進行中轉,從而達到求出最短路的目的。

返回來看程式碼,一句話概括:從i號頂點到j號頂點只經過前k號點的最短路程。

而我們再回頭看題意:

所有的邊全部給出,按照時間順序更新每一個可用的點(即修建好村莊),對於每個時間點進行兩點之間詢問,求對於目前建設的所有村莊來說任意兩點之間的最短路

不正好就是Floyd演算法中使用前k個節點更新最短路的思維嗎?

因此我們的解題思路就顯而易見了,按照時間不斷的解封新的點。

本題核心

inline void updata(int k){
	for(int i=0;i<n;i++)
	for(int j=0;j<n;j++)
	if(f[i][j]>f[i][k]+f[j][k])
	f[i][j]=f[j][i]=f[i][k]+f[j][k];//用這個新的更新所有前面的 
	return;
}

只更新到用前k個點

Ac_Code

#include<bits/stdc++.h>
using namespace std;
const int N = 210,INF = 0x3f3f3f3f;
int a[N],g[N][N];
int n,m;

void update(int idx)
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            g[j][i]=min(g[j][i],g[i][idx]+g[idx][j]),g[i][j]=g[j][i];
}

int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>a[i];
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)    
            if(i!=j) g[i][j]=INF;
            else g[i][j]=0;

    while(m--)
    {
        int u,v,t;
        cin>>u>>v>>t;
        g[u][v]=g[v][u]=t;
    }

    int q,idx=0;
    cin>>q;
    while(q--)
    {
        int u,v,t;
        cin>>u>>v>>t;
        while(idx<n&&a[idx]<=t)
        {
            update(idx);
            idx++;
        }
        if(a[u]>t||a[v]>t) puts("-1");
        else 
        {
            if(g[u][v]==INF) puts("-1");
            else cout<<g[u][v]<<endl;
        }
    }

    return 0;
}