DS博客做業06--圖




求投食~(點圖便可)

1.本週學習總結

1.1思惟導圖

1.2談談你對圖結構的認識及學習體會

圖中的頂點關係比樹的更加複雜,再也不是單純的層次關係,而是平等的,點與點均可能連通,因此存儲就須要模擬一個平面,在圖的關係比較稀疏是用鄰接表(使用線性存儲),反之使用鄰接矩陣,二維數據便可表示出一個平面。圖的問題,主要是遍歷和路徑,難點在於找到相應算法(或者多種算法結合),解決一些實際問題時通常都會對算法進行相應的改動。

2.PTA實驗做業

2.1.題目1:7-7 旅遊規劃

有了一張自駕旅遊路線圖,你會知道城市間的高速公路長度、以及該公路要收取的過路費。如今須要你寫一個程序,幫助前來諮詢的遊客找一條出發地和目的地之間的最短路徑。若是有若干條路徑都是最短的,那麼須要輸出最便宜的一條路徑。
輸入格式:
輸入說明:輸入數據的第1行給出4個正整數N、M、S、D,其中N(2≤N≤500)是城市的個數,順便假設城市的編號爲0~(N−1);M是高速公路的條數;S是出發地的城市編號;D是目的地的城市編號。隨後的M行中,每行給出一條高速公路的信息,分別是:城市一、城市二、高速公路長度、收費額,中間用空格分開,數字均爲整數且不超過500。輸入保證解的存在。
輸出格式:
在一行裏輸出路徑的長度和收費總額,數字間以空格分隔,輸出結尾不能有多餘空格。
輸入樣例:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
輸出樣例:
3 40算法

2.1.1設計思路

此題就是找最短路徑,能夠使用Dijkstra,使用一個包括距離和價錢的結構體建圖,而後比較時優先考慮距離其次到價格。

結構體:數組

typedef struct
{
    int weight=INF;//距離
    int cost=INF;//價格
}VNode;

僞代碼:網絡

int main()
{
    cin >> N >> M >> S >> D;
    輸入城市數量,和高速路和出發點、目的地 
    for (i = 0  to M) 
    {
        cin >> x >> y >> w >> c;
        讀入高速路信息
        graph[x][y].weight = graph[y][x].weight = w;//距離 
        graph[x][y].cost = graph[y][x].cost = c;//價格 
    }
    調用Dijkstra(S, D);
    return 0;
}

Dijkstra(S, D);函數app

void Dijkstra(int v,int d)
{
    VNode dist[501];//記錄最短路徑 
    int k;
    int s[501] = { 0 };//S[i]=1表示頂點i在S中,S[i]=0表示頂點i在u中 
    VNode mindis; 
    for (i = 0 to N)//N個頂點 
    {
        dist[i].weight = graph[v][i].weight;//距離初始化 
        dist[i].cost = graph[v][i].cost;//價格初始化 
    }
    s[v] = 1;
    for (i = 0 to N - 1)
    {
        mindis.weight = INF  初始化爲最大值 
        for (j = 0 toj < N)
        {
            if (s[j] == 0 && dist[j].weight <= mindis.weight)若是j屬於u中(沒有被選)而且距離小於等於最小值 
            {
                if (dist[j].weight < mindis.weight)距離小於最小值
                {
                    k = j;
                    mindis.weight = dist[j].weight;
                    mindis.cost = dist[j].cost;
                    把該頂點信息記錄 
                }
                else if(dist[j].cost < mindis.cost)距離相等,比較價格 
                {
                    k = j;
                    mindis.cost = dist[j].cost;
                    把該頂點信息記錄
                }
            }
        }
        s[k] = 1;
        for (j = 0 to N)
        {
            if(j點屬於u(沒有被選過))
                if(若是k和j連通)
                    if (graph[k][j].weight + dist[k].weight < dist[j].weight)若是過k點到j點的新路徑比原來短 
                    {
                        dist[j].weight = graph[k][j].weight + dist[k].weight;更新爲短路徑 
                        dist[j].cost = graph[k][j].cost + dist[k].cost;
                    }
                    else if(graph[k][j].weight + dist[k].weight == dist[j].weight)
                    {
                        if (graph[k][j].cost + dist[k].cost < dist[j].cost)若是過k點到j點的新路徑比原來便宜 
                        {
                            dist[j].cost = graph[k][j].cost + dist[k].cost;更新爲新價格 
                        }
                    }
        }
    }
    輸出最短路徑和價格 
}

2.1.2代碼截圖



2.2.3本題PTA提交列表說明


Q:

看錯題目而後誤覺得是輸出目的地和價格,而後覺得是bug找半天.。。。(還能過一個是最騷的),仔細看題目發現是輸出路徑的長度和價格函數

2.2.題目2:7-6 修建道路

N個村莊,從1到N編號,如今請您興建一些路使得任何兩個村莊彼此連通。咱們稱村莊A和B是連通的,當且僅當在A和B之間存在一條路,或者存在一個存在C,使得A和C之間有一條路,而且C和B是連通的。
已知在一些村莊之間已經有了一些路,您的工做是再興建一些路,使得全部的村莊都是連通的,而且興建的路的長度是最小的。
輸入格式:
第一行是一個整數N(3<=N<=100),表明村莊的數目。後面的N行,第i行包含N個整數,這N個整數中的第j個整數是第i個村莊和第j個村莊之間的距離,距離值在[1,1000]之間。
而後是一個整數Q(0<=Q<=N*(N+1)/2)。後面給出Q行,每行包含兩個整數a和b(1<=a<b<=N),表示在村莊a和b之間已經興建了路。
輸出格式:
輸出一行僅有一個整數,表示爲使全部的村莊連通須要新建公路的長度的最小值。
輸入樣例:
3
0 990 692
990 0 179
692 179 0
1
1 2
輸出樣例:
179學習

2.2.1設計思路

此題要求是修建公路使得任何兩個村莊都有路到達而且是最短,對於題中提到村莊之間已經有公路,只需把此類村莊的距離當作0便可。而後經過prim生成最小生成樹
注意:爲了簡單起見此題鄰接矩陣的0並不是常規prim算法中表明已經加入U(標記爲選過),而是表明距離爲0,標記則由visite[i]完成。
int main()
{ 
    for (i=1 to N) 
    {
        for (j = 1 to N) 
        {
            讀入村莊之間的距離到矩陣中 
        }
    }
    for (i = 0  to  q)
    {
        讀入已經修有路的村莊 
        graph[a][b] = graph[b][a]=0設置距離爲零 
    }
   調用prim函數 
    輸出最小修路長度 
    return 0;
}

prim函數spa

int Prim(int v)
{
    for (i = 1 to N)N個村莊 
    {
        對lowcost和closest數組初始化 
        lowcost[i] = graph[v][i]距離 
        closest[i] = v路徑 
    }
    visite[v] = 1標記已經加入U 
    for (i = 1 to N)
    {
        for (j = 1 to N)
        {
            查找lowcost中未加入U(即visite[j]=0)最小的點 
            用k記錄 
        }
        找到後把距離累加到sum中 
        把該點標記已經加入U 
        for (int j = 1; j <= N; j++)
        {
            修改lowcost和closet
            if (visite[j]== 0 && graph[k][j] < lowcost[j])若是經過k到未選的點有短的距離 
            {
                lowcost[j] = graph[k][j];
                closest[j] = k;
            }
        }
    }
    返回return sum;
}

2.2.2代碼截圖



2.2.3本題PTA提交列表說明


A:兩個wa,是此處以前沒有兩個置爲0(無向圖),設計

2.3.題目3:7-3 六度空間

六度空間」理論又稱做「六度分隔(Six Degrees of Separation)」理論。這個理論能夠通俗地闡述爲:「你和任何一個陌生人之間所間隔的人不會超過六個,也就是說,最多經過五我的你就可以認識任何一個陌生人。」如圖1所示。3d

假如給你一個社交網絡圖,請你對每一個節點計算符合「六度空間」理論的結點佔結點總數的百分比。
輸入格式:
輸入第1行給出兩個正整數,分別表示社交網絡圖的結點數N(1<N≤10
​4
​​,表示人數)、邊數M(≤33×N,表示社交關係數)。隨後的M行對應M條邊,每行給出一對正整數,分別是該條邊直接連通的兩個結點的編號(節點從1到N編號)。
輸出格式:
對每一個結點輸出與該結點距離不超過6的結點數佔結點總數的百分比,精確到小數點後2位。每一個結節點輸出一行,格式爲「結點編號:(空格)百分比%」。
輸入樣例:
10 9
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
輸出樣例:
1: 70.00%
2: 80.00%
3: 90.00%
4: 100.00%
5: 100.00%
6: 100.00%
7: 100.00%
8: 90.00%
9: 80.00%
10: 70.00%code

2.3.1設計思路

此題有點的像樹的層次遍歷,使用queue輔助搜索,visite[i]標記已經認識過的人,而後經過廣度優先搜索,把全部人都認識完或者已經達到第六層(最多經過五我的認識)就能夠結束搜索。
圖結構體
typedef struct
{
    int **edgs;(直接聲明數組會爆)
    double n, e;
}MatGraph;
int main()
{


    爲鄰接矩陣分配內存,直接聲明會爆 
    for (i =  0 to  M)鄰接矩陣初始化 
    {
        int x, y;
        cin >> x >> y;
        G.edgs[x][y] = G.edgs[y][x] = 1;
    }
    for (i =  1  to  N)調用N次廣搜 
    {
        調用BFS(G, i);
    }
    delete內存 
    return 0;
}
void BFS(MatGraph G,int v)
{
    使用cur表示當前訪問的頂點 ,last表示該層次的最後一個頂點
    當cur==last聲明該層次遍歷結束 
    while (!q.empty()&&level<6)//隊空或者層數到6 
    {
        從隊列去隊頭元素 temp =cur= q.front();
        for (int i = 1; i <=G.n; i++)
        {
            if (G.edgs[temp][i] != 0 && visite[i] == 0)尋找經過當前點能夠認識其餘點 
            {
                visite[i] = 1;標記已認識 
                q.push(i);入隊 
                sum++;認識人數 
            }
        }
        if (cur == last)//遍歷一層結束 
        {
            if (!q.empty())
            {
                last = q.back();
                level++;
            }
        }
    }
    printf("%d: %.2f%%\n",v,sum*100 / (G.n));輸出結果 
}

2.3.2代碼截圖

2.3.3本題PTA提交列表說明


A:直接過了,注意下層次和標記就能夠了,

三、上機考試錯題及處理辦法(-2--2分)

3.1.截圖錯題代碼

3.1.1題目:六度空間

3.2 錯的緣由及處理方法

visite[i]等於1纔是標記爲已選,可是打錯,而後編譯器一直提示的是內存爆了,我覺得是數組問題,後來才發現是該處錯誤引起的無限循環。
相關文章
相關標籤/搜索