1.本周學習總結(0--2分)
1.思維導圖
2.談談你對圖結構的認識及學習體會。
這章學習了圖,學習了圖的兩種存儲結構:鄰接矩陣和鄰接表。這兩種存儲結構都用到了之前學c時學到的結構體,將結構體充分運用。知道了圖的兩種遍歷方法:深度優先遍歷(DFS)和廣度優先遍歷(BFS)。深度優先遍歷是一個對每個結點查找其鄰接點的過程,而廣度優先遍歷則搜索了所有節點。
通過學習Prim算法和Kruskal算法,解決了最小生成樹問題。在學習Prim算法的同時,還提到了貪心算法,之前學習的貪心算法只能解決局部最優的問題,所以最小生成樹的問題不可以用貪心算法來做。
學習最短路徑時,先學的Dijstra算法,但是Dijstra算法存在只能解決最短路徑,而不能解決最長路徑的問題,由此引進了Floyd算法,在滿足最小路徑查找的同時也能滿足最長路徑的查找。
拓撲排序和關鍵路徑都是對有向無環圖的操作。拓撲排序可以用來判斷一個有向圖是否有環,還可以解決教學系統中的排課問題;關鍵路徑則是用來解決最短工時的問題。
2.PTA實驗作業(6分)
2.1.7-1 圖着色問題
圖着色問題是一個著名的NP完全問題。給定無向圖G=(V,E),問可否用K種顏色為V中的每一個頂點分配一種顏色,使得不會有兩個相鄰頂點具有同一種顏色?
但本題並不是要你解決這個着色問題,而是對給定的一種顏色分配,請你判斷這是否是圖着色問題的一個解。
2.1.1設計思路(偽代碼)
//設計思路
先建一個無向圖的鄰接矩陣。在每次判斷解是否正確的過程中:先判斷使用的顏色是否為k種,是,則繼續操作,反之,輸出“No”進入下一輪循環;用雙重for循環判斷每個結點的臨邊顏色是否符合要求。
//偽代碼(主函數)
定義三個整型變量v、e、k、n,分別用於存放結點數、邊數、顏色數,和 解的數量;
輸入v、e、k;
定義一個MGraph型變量G;
利用CreatMGrap函數創建無向圖;
輸入解的數量n;
while n-- do
定義int型變量:flag=1,用於控制解不正確時的情況;num數組,用於存儲各個結點的顏色;count=0,用於計算各個接中使用的顏色數量;hash數組,用於控制顏色數量的計算;
for i=0 to G.n do
輸入num[i];
if hash[num[i]]等於0 then //num[i]顏色沒出現過時
hash[num[i]]++;
count++;
end if
end for
if count的值與k不相等時 then
輸出“No”
continue進入下一輪循環
end if
for i=0 to G.n do
for j=i to G.n do //無向圖的鄰接矩陣關於對角線對稱,所以只要判斷半個鄰接矩陣
if i與j不相等 then
if i與j結點的顏色相同 且 i與j結點間有邊 then
輸出“No”
flag=0
break
end if
end if
end for
if flag=0 then
break
end if
end for
if flag=1 then
輸出“Yes”
end if
end while
2.1.2代碼截圖(注意,截圖,截圖,截圖。不要粘貼博客上。)
2.1.3本題PTA提交列表說明。
- Q1:第一次提交,是把判斷解是否正確的那一部分寫成一個函數的,結果提交上去顯示答案錯誤。當時以為我的函數有什么問題,就把函數拆了,直接寫到主函數里頭,結果還是答案錯誤。
- A1:我想着代碼沒問題啊,調試也沒毛病,突然,想到答案錯誤還有一種情況:輸出的問題,看一眼題目要求,好吧,yes和no的首字母要大寫,我沒大寫。
- Q2:然后,改完以后,部分正確,還有兩分不知道錯在哪,提示的是有小於k種顏色的情況錯誤。
- A2:當時在想,我的做法小於k種顏色的情況也可以正確判斷啊,為什么會顯示這個錯誤。當時舍友在一邊,我就問她着色的時候可不可以不用到k種顏色這么多。她說,當然可以啊。然后,我就很納悶,到底哪兒錯了。后來抱着試一試的心態,將使用的顏色小於k的情況也當走是錯的,結果就過了。
2.2 7-6 修建道路
N個村庄,從1到N編號,現在請您興建一些路使得任何兩個村庄彼此連通。我們稱村庄A和B是連通的,當且僅當在A和B之間存在一條路,或者存在一個存在C,使得A和C之間有一條路,並且C和B是連通的。
已知在一些村庄之間已經有了一些路,您的工作是再興建一些路,使得所有的村庄都是連通的,並且興建的路的長度是最小的。
2.2.1設計思路(偽代碼)
//偽代碼(Prim函數)
定義一個int型數組lowcost[],變量MIN用於存放最小值,v,賦初值為1,cost用於計算花費,賦初值為0;
定義一個int型數組closest[],用於存放最近的結點,變量i,j,k,用於循環中
定義一個ArcNode型變量p
將0賦值給lowcost[v]
for i=2 to 圖的節點數 do
lowcost[i]=10000001 //賦初值,令數組的初值最大
end for
將G->adjlist[v].firstarc的值賦給p
while p不為空 do
將p->weight的值賦給lowcost[p->adjvex]
將v的值賦給closest[p->adjvex]
令p等於p指向的下一個結點
end while
for i =1 to 圖的節點數 do
賦初值1000000給MIN
for j=1 to 圖的結點數 do
if lowcost[j]不等於-1 且 小於MIN then
將 lowcost[j]的值賦給MIN
將j的值賦給k
end if
end for
將MIN的值累加給cost
lowcost[k]=-1
將G->adjlist[k].firstarc的值賦給p
while p不為空 do
if p->weight小於lowcost[p->adjvex] 且 lowcost[p->adjvex]不等於-1 then
將p->weight的值賦給lowcost[p->adjvex]
將k的值賦給closest[p->adjvex]
end if
令p等於p指向的下一個結點
end while
end while
輸出cost
2.2.2代碼截圖(注意,截圖,截圖,截圖。不要粘貼博客上。)
2.2.3本題PTA提交列表說明。
- Q1:這題答案錯誤,一開始沒發現什么毛病,該賦值的也賦值了,后來無意間發現,好吧,賦初值的位置放錯了。
- A1:改過來之后就對了。
2.3 7-7 旅游規划
有了一張自駕旅游路線圖,你會知道城市間的高速公路長度、以及該公路要收取的過路費。現在需要你寫一個程序,幫助前來咨詢的游客找一條出發地和目的地之間的最短路徑。如果有若干條路徑都是最短的,那么需要輸出最便宜的一條路徑。
2.3.1設計思路(偽代碼)
//偽代碼(Dijkstra函數)
定義int型變量v,i,MIN1,MIN2
定義ArcNode型變量p
定義int型數組dist1[1000]、path[1000]、dist2[1000]
定義一個int型靜態局部變量數組visted[1000]
for i=0 to 圖的節點數 do
dist1[i]=100000
dist2[i]=100000
path[i]=-1
end for
將Begin的值賦給v
將0分別賦給dist1[v]和dist2[v],將v賦給path[v]
while 1 do
將100000分別賦給MIN1和MIN2
for i=0 to 圖的結點數 do
if dist1[i]的值小於MIN1 且 visted不等於1 then
if dist1[i]的值小於MIN1 或者 dist2[i]的值小於MIN2 then
將dist1[i]的值賦給MIN1
將dist2[i]的值賦給MIN2
將i的值賦給v
end if
end if
end for
if v等於END then
退出循環
end if
visted[v]=1
將G->adjlist[v].firstarc的值賦給p
while p不為空時 do
if p->length與diat1[v]的和 小於等於 dist1[p->adjvex] then
if p->length與diat1[v]的和 小於 dist1[p->adjvex] 或者 p->price與diat2[v]的和 小於 dist2[p->adjvex] then
將p->length與diat1[v]的和賦給dist1[p->adjvex]
將p->price與diat2[v]的和 賦給dist2[p->adjvex]
將v的值賦給path[p->adjvex]
end if
end if
p等於p指向的下一個結點
end while
end while
輸出dist1[v]和dist2[v]的值
2.3.2代碼截圖(注意,截圖,截圖,截圖。不要粘貼博客上。)
2.3.3本題PTA提交列表說明。
- 這題主要是關於迪傑斯特拉算法的一個應用。代碼基本都是照着書上的代碼修修改改完成的。然后調試什么的都在VS上完成了。
3、上機考試錯題及處理辦法(-2--2分)
- 當時上機考試的時候,因為時間問題和對這章知識的不熟悉,只做了兩道題(兩道題都做出來了)。當時還剩幾分鍾的時候看了一下六度空間的題目,當時代碼打了一半半時間就到了,就沒打完,就把回來后打的代碼貼上來。
//解題思路
利用廣度優先遍歷的算法來找到距離小於6的結點個數,來算出百分比
//偽代碼(bfs函數)
定義int型變量i,數組vis[10001],並賦初值為0
定義int型變量last,令其等於num(用來記錄每層的最后一個元素);tail,用於記錄每層壓入時的結點,level,並賦初值為0;count賦初值為1
定義一個int型隊列q
將num入隊
將1賦給vis[num]
while q不為空時 do
將隊頭的值賦給num
出隊
for i=1 to v do
if g[num][i]等於1 且 vis[i]等於0 then
count++
將1賦給vis[i]
將i入隊
將i 賦給tail
end if
end for
if last等於num then //彈出的x等於當前層的最后一個元素
level++
將tail的值賦給last
end if
if level的值為6時 then
退出循環
end if
end while
將count的值返回主函數