1. 程式人生 > >網絡提速(最短路)

網絡提速(最短路)

三臺 oid size 註意 減少 組成 getchar() cst etc

codevs——1243 網絡提速

時間限制: 1 s 空間限制: 128000 KB 題目等級 : 黃金 Gold 題目描述 Description

某學校的校園網由n(1<=n<=50)臺計算機組成,計算機之間由網線相連,如圖5。其中頂點代表計算機,邊代表網線。正如你所見,不同網線的傳輸能力不盡相同,例如計算機1與計算機2之間傳輸信息需要34秒,而計算機2與計算機3之間的傳輸信息只要10秒。計算機1與計算機5之間傳輸信息需要44秒,途徑為機1到機3到機5。

現學校購買了m(1<=m<=10)臺加速設備,每臺設備可作用於一條網線,使網線上傳輸信息用時減半。多臺設備可用於同一條網線,其效果疊加,即用兩臺設備,用時為原來的1/4,用三臺設備,用時為原來的1/8。如何合理使用這些設備,使計算機1到計算機n傳輸用時最少,這個問題急需解決。校方請你編程解決這個問題。例如圖5,若m=2,則將兩臺設備分別用於1-3,3-5的線路,傳輸用時可減少為22秒,這是最佳解。

輸入描述 Input Description

第一行先輸入n,m。以下n行,每行有n個實數。第i行第j列的數為計算機i與計算機j之間網線的傳輸用時,0表示它們之間沒有網線連接。註意輸入數據中,從計算機1到計算機n至少有一條網路。

輸出描述 Output Description

輸出計算機1與計算機n之間傳輸信息的最短時間。(保留兩位小數)

樣例輸入 Sample Input

5 2

0 34 24 0 0

34 0 10 12 0

24 10 0 16 20

0 12 16 0 30

0 0 20 30 0

樣例輸出 Sample Output

22.00

思路:先對整體進行處理,然後跑一遍最短路(我用的是spfa),在這個spfa中加上dp來解決這道題。

首先:我們在這裏存邊的時候我們使用的是一個三維數組,用a[i][j][0]存我們輸入的每條邊的邊權。

從a[i][j][1]到a[i][j][k]存的是我們如果在這條邊上使用k個加速器後產生的效果。(當然,裏面邊不相連的權值賦成極大值,這樣就方便我們後面用來跑spfa)

然後這樣我們就把一個比較復雜的問題轉化成了一個比較簡單的問題了。

對於這個問題我們就可以看作一個簡單的spfa了。

但是別高興的太早,我們並不是就這個樣子就可以A掉這個題的哦,我們還要再加一點東西。

註意:spfa裏面跑的是三重循環,第一重循環跑起點,第二重循環跑的是使用的加速器的個數。

代碼:

#include<stdio.h>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100
#define M 20
#define oo 1234567
using namespace std;
int n,m,q[N*N];
double dis[N][M],a[N][N][M];
bool b[N]={0};
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<0||ch>9)
    {
        if(ch==-) f=-1;
        ch=getchar();
    }
    while(ch>=0&&ch<=9)
    {
        x=x*10+ch-0;
        ch=getchar();
    }
    return x*f;
}
void spfa()
{
    int head(0),tail(1),u;
    q[1]=1;
    b[1]=1;
    do
      {
           head++;
           u=q[head];
           b[u]=0;
           for (int i=1;i<=n;i++)
             if (i!=u)
               for (int j=0;j<=m;j++)//從1到u使用j個加速器 
                 for (int k=0;k<=m-j;k++)//從u到i使用k個加速器,同時要保證j+k<=m 
                   if (dis[u][j]+a[u][i][k]<dis[i][j+k])
                     {
                          dis[i][j+k]=dis[u][j]+a[u][i][k];
                          if (!b[i]) q[++tail]=i,b[i]=1;
                   }
      }while (head<tail);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      {
          scanf("%lf",&a[i][j][0]);
          if(!a[i][j][0])
           for(int k=0;k<=m;k++)
          a[i][j][k]=oo;
        else 
         for(int k=1;k<=m;k++)
          a[i][j][k]=a[i][j][k-1]/2;
      }
    for(int i=2;i<=n;i++)
     for(int j=0;j<=m;j++)
       dis[i][j]=oo;
    spfa();
    printf("%.2lf",dis[n][m]);
    return 0;
}

網絡提速(最短路)